diff options
Diffstat (limited to 'src/plugins/projectexplorer/projectwindow.cpp')
-rw-r--r-- | src/plugins/projectexplorer/projectwindow.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp new file mode 100644 index 0000000000..94532c4131 --- /dev/null +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception version +** 1.2, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ +#include "project.h" +#include "projectwindow.h" +#include "projectexplorer.h" +#include "projectexplorerconstants.h" +#include "iprojectproperties.h" +#include "session.h" +#include "projecttreewidget.h" + +#include <coreplugin/minisplitter.h> +#include <coreplugin/fileiconprovider.h> +#include <coreplugin/icore.h> + +#include <QtCore/QDebug> +#include <QtGui/QBoxLayout> +#include <QtGui/QComboBox> +#include <QtGui/QTabWidget> +#include <QtGui/QToolBar> +#include <QtGui/QTreeWidget> +#include <QtGui/QHeaderView> + +using namespace ProjectExplorer; +using namespace ProjectExplorer::Internal; + +namespace { +bool debug = false; +} + +ProjectWindow::ProjectWindow(Core::ICore *core, + QWidget *parent) : + QWidget(parent), + m_core(core) +{ + setWindowTitle(tr("Project Explorer")); + setWindowIcon(QIcon(":/projectexplorer/images/projectexplorer.png")); + + ExtensionSystem::PluginManager *pm = m_core->pluginManager(); + ProjectExplorerPlugin *projectExplorer = m_projectExplorer = pm->getObject<ProjectExplorerPlugin>(); + m_session = 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->setFrameStyle(QFrame::NoFrame); + m_treeWidget->setRootIsDecorated(false); + m_treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); + m_treeWidget->setHeaderLabels(QStringList() + << tr("Projects") + << tr("Startup") + << tr("Path") + ); + + connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), + this, SLOT(handleItem(QTreeWidgetItem*, int)), Qt::QueuedConnection); + connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem *)), + this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*))); + + QWidget *panelsWidget = new QWidget; + m_panelsTabWidget = new QTabWidget; + m_panelsTabWidget->setDocumentMode(true); + QVBoxLayout *panelsLayout = new QVBoxLayout(panelsWidget); + + panelsLayout->setSpacing(0); + panelsLayout->setContentsMargins(0, panelsLayout->margin(), 0, 0); + panelsLayout->addWidget(m_panelsTabWidget); + + QWidget *dummy = new QWidget; + QVBoxLayout *dummyLayout = new QVBoxLayout(dummy); + dummyLayout->setMargin(0); + dummyLayout->setSpacing(0); + dummyLayout->addWidget(new QToolBar(dummy)); + dummyLayout->addWidget(m_treeWidget); + + QSplitter *splitter = new Core::MiniSplitter; + splitter->setOrientation(Qt::Vertical); + splitter->addWidget(dummy); + splitter->addWidget(panelsWidget); + + + + // make sure that the tree treewidget has same size policy as qtabwidget + m_treeWidget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); + const int treeWidgetMinSize = m_treeWidget->minimumSizeHint().height(); + splitter->setSizes(QList<int>() << treeWidgetMinSize << splitter->height() - treeWidgetMinSize); + + QVBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->setMargin(0); + 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())); +} + +ProjectWindow::~ProjectWindow() +{ +} + +void ProjectWindow::restoreStatus() +{ + 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); + } +} + +void ProjectWindow::saveStatus() +{ + m_session->setValue(QLatin1String("ProjectWindow/Panel"), m_panelsTabWidget->currentIndex()); +} + +void ProjectWindow::showProperties(ProjectExplorer::Project *project, const QModelIndex & /* subIndex */) +{ + if (debug) + qDebug() << "ProjectWindow - showProperties called"; + + // Remove the tabs from the tab widget first + while (m_panelsTabWidget->count() > 0) + m_panelsTabWidget->removeTab(0); + + while (m_panels.count()) { + PropertiesPanel *panel = m_panels.at(0); + m_panels.removeOne(panel); + delete panel; + } + + if (project) { + QList<IPanelFactory *> pages = + ExtensionSystem::PluginManager::instance()->getObjects<IPanelFactory>(); + foreach (IPanelFactory *panelFactory, pages) { + if (panelFactory->supports(project)) { + PropertiesPanel *panel = panelFactory->createPanel(project); + if (debug) + qDebug() << "ProjectWindow - setting up project properties tab " << panel->name(); + + m_panels.append(panel); + m_panelsTabWidget->addTab(panel->widget(), panel->name()); + } + } + } +} + +void ProjectWindow::updateTreeWidget() +{ + // 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.... + m_treeWidget->setFocus(); + m_treeWidget->clear(); + + foreach(Project *project, m_session->projects()) { + const QFileInfo fileInfo(project->file()->fileName()); + + 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); + } + + m_treeWidget->addTopLevelItem(item); + + if (m_projectExplorer->currentProject() == project) { + m_treeWidget->setCurrentItem(item, 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } + } + + + if (!m_treeWidget->currentItem()) { + if (m_treeWidget->topLevelItemCount() > 0) + m_treeWidget->setCurrentItem(m_treeWidget->topLevelItem(0), 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + else + handleCurrentItemChanged(0); + } + + + // Hack around Qt bug + m_treeWidget->viewport()->update(); +} + + +Project *ProjectWindow::findProject(const QString &path) const +{ + QList<Project*> projects = m_session->projects(); + foreach(Project* project, projects) { + if (project->file()->fileName() == path) { + return project; + } + } + return 0; + } + + +void ProjectWindow::handleCurrentItemChanged(QTreeWidgetItem *current) +{ + if (current) { + QString path = current->text(2); + if (Project *project = findProject(path)) { + + m_projectExplorer->setCurrentFile(project, path); + showProperties(project, QModelIndex()); + return; + } + } + + // we only get here if either current is zero or we didn't find a project for the path + m_projectExplorer->setCurrentFile(0, QString()); + 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 { + m_session->setStartupProject(project); + } + } +} |