projectwindow.cpp 13 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11 12 13 14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
25
** If you are unsure which license is appropriate for your use, please
26
** contact the sales department at http://www.qtsoftware.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
#include "projectwindow.h"
hjk's avatar
hjk committed
31 32

#include "project.h"
con's avatar
con committed
33 34 35 36 37 38 39 40 41
#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>
42
#include <extensionsystem/pluginmanager.h>
con's avatar
con committed
43
#include <utils/styledbar.h>
con's avatar
con committed
44 45

#include <QtCore/QDebug>
46
#include <QtGui/QApplication>
con's avatar
con committed
47 48
#include <QtGui/QBoxLayout>
#include <QtGui/QComboBox>
49
#include <QtGui/QScrollArea>
con's avatar
con committed
50 51 52
#include <QtGui/QTabWidget>
#include <QtGui/QTreeWidget>
#include <QtGui/QHeaderView>
dt's avatar
dt committed
53
#include <QtGui/QLabel>
con's avatar
con committed
54 55 56 57 58 59 60 61

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace {
bool debug = false;
}

dt's avatar
dt committed
62 63 64
PanelsWidget::PanelsWidget(QWidget *parent)
    : QScrollArea(parent)
{
con's avatar
con committed
65 66 67 68 69 70 71 72 73
    QWidget *topwidget = new QWidget;
    QHBoxLayout *topwidgetLayout = new QHBoxLayout;
    topwidgetLayout->setMargin(0);
    topwidgetLayout->setSpacing(0);
    topwidget->setLayout(topwidgetLayout);

    QWidget *verticalWidget = new QWidget;
    verticalWidget->setMaximumWidth(800);
    m_layout = new QVBoxLayout;
dt's avatar
dt committed
74
    m_layout->addStretch(10);
con's avatar
con committed
75 76 77
    verticalWidget->setLayout(m_layout);
    topwidgetLayout->addWidget(verticalWidget);
    topwidgetLayout->addStretch(10);
dt's avatar
dt committed
78 79 80

    setWidgetResizable(true);
    setFrameStyle(QFrame::NoFrame);
con's avatar
con committed
81
    setWidget(topwidget);
dt's avatar
dt committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
}

PanelsWidget::~PanelsWidget()
{
    clear();
}

void PanelsWidget::addWidget(const QString &name, QWidget *widget)
{
    Panel p;
    p.nameLabel = new QLabel(this);
    p.nameLabel->setText(name);
    QFont f = p.nameLabel->font();
    f.setBold(true);
    f.setPointSizeF(f.pointSizeF() * 1.4);
    p.nameLabel->setFont(f);
    p.panelWidget = widget;

dt's avatar
dt committed
100 101 102 103 104 105 106 107
    m_layout->insertWidget(m_layout->count() -1, p.nameLabel);
    QHBoxLayout *hboxLayout = new QHBoxLayout();
    hboxLayout->setContentsMargins(20, 0, 0, 0);
    hboxLayout->addWidget(p.panelWidget);
    p.marginLayout = hboxLayout;
    m_layout->insertLayout(m_layout->count() -1, hboxLayout);

    m_panels.append(p);
dt's avatar
dt committed
108 109 110 111 112 113 114
}

void PanelsWidget::clear()
{
    foreach(Panel p, m_panels) {
        delete p.nameLabel;
        delete p.panelWidget;
dt's avatar
dt committed
115
        delete p.marginLayout;
dt's avatar
dt committed
116 117 118 119
    }
    m_panels.clear();
}

dt's avatar
dt committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
///
// ProjectView
///

ProjectView::ProjectView(QWidget *parent)
    : QTreeWidget(parent)
{
    m_sizeHint = QSize(250, 250);
    setUniformRowHeights(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    QAbstractItemModel *m = model();
    connect(m, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(updateSizeHint()));
    connect(m, SIGNAL(rowsRemoved(QModelIndex,int,int)),
            this, SLOT(updateSizeHint()));
    connect(m, SIGNAL(modelReset()),
            this, SLOT(updateSizeHint()));
    connect(m, SIGNAL(layoutChanged()),
            this, SLOT(updateSizeHint()));
    updateSizeHint();
}

ProjectView::~ProjectView()
{

}

QSize ProjectView::sizeHint() const
{
    return m_sizeHint;
}

void ProjectView::updateSizeHint()
{
    if (!model()) {
        m_sizeHint = QSize(250, 250);
        return;
    }

    int heightOffset = size().height() - viewport()->height();
    int heightPerRow = sizeHintForRow(0);
    if (heightPerRow == -1) {
        heightPerRow = 30;
    }
    int rows = qMin(qMax(model()->rowCount(), 2), 6);
    int height = rows * heightPerRow + heightOffset;
    if (m_sizeHint.height() != height) {
        m_sizeHint.setHeight(height);
        updateGeometry();
    }
}

dt's avatar
dt committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
///
// OnePixelBlackLine
///

#include <QtGui/QPainter>
#include <QtGui/QPaintEvent>
#include <utils/stylehelper.h>

class OnePixelBlackLine : public QWidget
{
public:
    OnePixelBlackLine(QWidget *parent)
        : QWidget(parent)
    {
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        setMinimumHeight(1);
        setMaximumHeight(1);
    }
    void paintEvent(QPaintEvent *e)
    {
        QPainter p(this);
        p.fillRect(e->rect(), QBrush(StyleHelper::borderColor()));
    }
};

dt's avatar
dt committed
198 199 200 201 202

///
// ProjectWindow
///

dt's avatar
dt committed
203 204
ProjectWindow::ProjectWindow(QWidget *parent)
    : QWidget(parent), m_currentItemChanged(false)
con's avatar
con committed
205 206 207 208
{
    setWindowTitle(tr("Project Explorer"));
    setWindowIcon(QIcon(":/projectexplorer/images/projectexplorer.png"));

209 210
    m_projectExplorer = ProjectExplorerPlugin::instance();
    m_session = m_projectExplorer->session();
con's avatar
con committed
211

dt's avatar
dt committed
212
    m_treeWidget = new ProjectView(this);
dt's avatar
dt committed
213 214
    m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    m_treeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
con's avatar
con committed
215 216 217 218 219 220 221 222 223 224
    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)),
dt's avatar
dt committed
225
            this, SLOT(handleItem(QTreeWidgetItem*, int)));
con's avatar
con committed
226 227 228
    connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem *)),
            this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*)));

dt's avatar
dt committed
229
    m_panelsWidget = new PanelsWidget(this);
con's avatar
con committed
230

dt's avatar
dt committed
231 232
    QVBoxLayout *topLevelLayout = new QVBoxLayout(this);
    topLevelLayout->setMargin(0);
dt's avatar
dt committed
233
    topLevelLayout->setSpacing(0);
dt's avatar
dt committed
234 235
    topLevelLayout->addWidget(new Core::Utils::StyledBar(this));
    topLevelLayout->addWidget(m_treeWidget);
dt's avatar
dt committed
236
    topLevelLayout->addWidget(new OnePixelBlackLine(this));
dt's avatar
dt committed
237
    topLevelLayout->addWidget(m_panelsWidget);
con's avatar
con committed
238

dt's avatar
dt committed
239 240 241 242 243 244 245
    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*)));
con's avatar
con committed
246 247 248 249 250 251 252 253
}

ProjectWindow::~ProjectWindow()
{
}

void ProjectWindow::restoreStatus()
{
dt's avatar
dt committed
254 255 256 257
    if (!m_treeWidget->currentItem() && m_treeWidget->topLevelItemCount()) {
        m_treeWidget->setCurrentItem(m_treeWidget->topLevelItem(0), 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
    }

dt's avatar
dt committed
258 259 260 261 262 263 264 265 266 267
    // TODO
//    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);
con's avatar
con committed
268 269 270 271
}

void ProjectWindow::saveStatus()
{
dt's avatar
dt committed
272 273
    // TODO
//    m_session->setValue(QLatin1String("ProjectWindow/Panel"), m_panelsTabWidget->currentIndex());
con's avatar
con committed
274 275 276 277 278 279 280 281
}

void ProjectWindow::showProperties(ProjectExplorer::Project *project, const QModelIndex & /* subIndex */)
{
    if (debug)
        qDebug() << "ProjectWindow - showProperties called";

    // Remove the tabs from the tab widget first
dt's avatar
dt committed
282
    m_panelsWidget->clear();
con's avatar
con committed
283 284 285 286 287 288 289 290 291

    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();
dt's avatar
dt committed
292
                m_panelsWidget->addWidget(panel->name(), panel->widget());
con's avatar
con committed
293 294 295 296 297
            }
        }
    }
}

dt's avatar
dt committed
298
void ProjectWindow::updateTreeWidgetStatupProjectChanged(ProjectExplorer::Project *startupProject)
con's avatar
con committed
299
{
dt's avatar
dt committed
300 301 302
    int count = m_treeWidget->topLevelItemCount();
    for (int i = 0; i < count; ++i) {
        QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
303
        if (Project *project = findProject(item->data(2, Qt::UserRole).toString())) {
dt's avatar
dt committed
304 305 306 307 308
            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);
309 310
        }
    }
dt's avatar
dt committed
311
}
con's avatar
con committed
312

dt's avatar
dt committed
313 314 315 316
void ProjectWindow::updateTreeWidgetProjectAdded(ProjectExplorer::Project *projectAdded)
{
    int position = m_session->projects().indexOf(projectAdded);
    const QFileInfo fileInfo(projectAdded->file()->fileName());
con's avatar
con committed
317

dt's avatar
dt committed
318
    QTreeWidgetItem *item = new QTreeWidgetItem();
319
    item->setText(0, projectAdded->name());
dt's avatar
dt committed
320
    item->setIcon(0, Core::FileIconProvider::instance()->icon(fileInfo));
321 322
    item->setData(2, Qt::UserRole, fileInfo.filePath());
    item->setText(2, QDir::toNativeSeparators(fileInfo.filePath()));
con's avatar
con committed
323

dt's avatar
dt committed
324 325 326 327
    if (projectAdded->isApplication()) {
        bool checked = (m_session->startupProject() == projectAdded);
        item->setCheckState(1, checked ? Qt::Checked : Qt::Unchecked);
    }
con's avatar
con committed
328

dt's avatar
dt committed
329 330
    m_treeWidget->insertTopLevelItem(position, item);
}
con's avatar
con committed
331

dt's avatar
dt committed
332 333 334 335
void ProjectWindow::updateTreeWidgetAboutToRemoveProject(ProjectExplorer::Project *projectRemoved) {
    int count = m_treeWidget->topLevelItemCount();
    for (int i = 0; i < count; ++i) {
        QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
336
        if (item->data(2, Qt::UserRole).toString() == QFileInfo(projectRemoved->file()->fileName()).filePath()) {
dt's avatar
dt committed
337 338 339 340
            if (m_treeWidget->currentItem() == item) {
                    m_treeWidget->setCurrentItem(0);
            }
        }
con's avatar
con committed
341 342 343
    }
}

dt's avatar
dt committed
344 345 346 347 348
void ProjectWindow::updateTreeWidgetProjectRemoved(ProjectExplorer::Project *projectRemoved)
{    
    int count = m_treeWidget->topLevelItemCount();
    for (int i = 0; i < count; ++i) {
        QTreeWidgetItem *item = m_treeWidget->topLevelItem(i);
349
        if (item->data(2, Qt::UserRole).toString() == QFileInfo(projectRemoved->file()->fileName()).filePath()) {
dt's avatar
dt committed
350 351 352 353 354 355
            QTreeWidgetItem *it = m_treeWidget->takeTopLevelItem(i);
            delete it;
            break;
        }
    }
}
con's avatar
con committed
356 357 358 359

Project *ProjectWindow::findProject(const QString &path) const
{
    QList<Project*> projects = m_session->projects();
hjk's avatar
hjk committed
360
    foreach (Project* project, projects)
dt's avatar
dt committed
361
        if (QFileInfo(project->file()->fileName()).filePath() == path)
con's avatar
con committed
362 363
            return project;
    return 0;
hjk's avatar
hjk committed
364
}
con's avatar
con committed
365 366 367 368


void ProjectWindow::handleCurrentItemChanged(QTreeWidgetItem *current)
{
dt's avatar
dt committed
369 370 371
    if (m_currentItemChanged)
        return;
    m_currentItemChanged = true;
con's avatar
con committed
372
    if (current) {
373
        QString path = current->data(2, Qt::UserRole).toString();
con's avatar
con committed
374 375 376
        if (Project *project = findProject(path)) {
            m_projectExplorer->setCurrentFile(project, path);
            showProperties(project, QModelIndex());
dt's avatar
dt committed
377
            m_currentItemChanged = false;
con's avatar
con committed
378 379 380
            return;
        }
    }
dt's avatar
dt committed
381 382
    showProperties(0, QModelIndex());
    m_currentItemChanged = false;
con's avatar
con committed
383 384 385 386 387 388 389 390
}


void ProjectWindow::handleItem(QTreeWidgetItem *item, int column)
{
    if (!item || column != 1) // startup project
        return;

391
    const QString path = item->data(2, Qt::UserRole).toString();
con's avatar
con committed
392
    Project *project = findProject(path);
dt's avatar
dt committed
393 394 395
    // Project no longer exists
    if (!project)
        return;
396 397 398 399 400 401 402 403 404
     if (!(item->checkState(1) == Qt::Checked)) { // is now unchecked
         if (m_session->startupProject() == project) {
             item->setCheckState(1, Qt::Checked); // uncheck not supported
         }
     } else if (project && project->isApplication()) { // is now checked
         m_session->setStartupProject(project);
     } else {
         item->setCheckState(1, Qt::Unchecked); // check not supported
     }
con's avatar
con committed
405
}