projectwindow.cpp 13.4 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 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
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.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

con's avatar
con committed
32 33
#include "doubletabwidget.h"

hjk's avatar
hjk committed
34
#include "project.h"
35
#include "environment.h"
con's avatar
con committed
36 37 38 39
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "iprojectproperties.h"
#include "session.h"
Tobias Hunger's avatar
Tobias Hunger committed
40
#include "target.h"
con's avatar
con committed
41
#include "projecttreewidget.h"
dt's avatar
dt committed
42
#include "runconfiguration.h"
Tobias Hunger's avatar
Tobias Hunger committed
43 44 45
#include "buildsettingspropertiespage.h"
#include "runsettingspropertiespage.h"
#include "targetsettingspanel.h"
con's avatar
con committed
46 47 48 49

#include <coreplugin/minisplitter.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
50
#include <coreplugin/ifile.h>
51
#include <extensionsystem/pluginmanager.h>
Tobias Hunger's avatar
Tobias Hunger committed
52
#include <utils/qtcassert.h>
con's avatar
con committed
53
#include <utils/styledbar.h>
54
#include <utils/stylehelper.h>
con's avatar
con committed
55

56
#include <QtGui/QApplication>
con's avatar
con committed
57 58
#include <QtGui/QBoxLayout>
#include <QtGui/QComboBox>
59
#include <QtGui/QScrollArea>
dt's avatar
dt committed
60
#include <QtGui/QLabel>
dt's avatar
dt committed
61 62
#include <QtGui/QPainter>
#include <QtGui/QPaintEvent>
63 64
#include <QtGui/QMenu>

con's avatar
con committed
65 66 67 68
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace {
Tobias Hunger's avatar
Tobias Hunger committed
69
const int ICON_SIZE(64);
Tobias Hunger's avatar
Tobias Hunger committed
70 71 72 73

const int ABOVE_HEADING_MARGIN(10);
const int ABOVE_CONTENTS_MARGIN(4);
const int BELOW_CONTENTS_MARGIN(16);
Tobias Hunger's avatar
Tobias Hunger committed
74

75
} // anonymous namespace
Tobias Hunger's avatar
Tobias Hunger committed
76

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
///
// OnePixelBlackLine
///

class OnePixelBlackLine : public QWidget
{
public:
    OnePixelBlackLine(QWidget *parent)
        : QWidget(parent)
    {
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        setMinimumHeight(1);
        setMaximumHeight(1);
    }
    void paintEvent(QPaintEvent *e)
    {
Tobias Hunger's avatar
Tobias Hunger committed
93
        Q_UNUSED(e);
94
        QPainter p(this);
95 96 97
        QColor fillColor = Utils::StyleHelper::mergedColors(
                palette().button().color(), Qt::black, 80);
        p.fillRect(contentsRect(), fillColor);
98 99 100
    }
};

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
101 102 103 104 105 106 107 108 109 110 111 112
class RootWidget : public QWidget
{
public:
    RootWidget(QWidget *parent) : QWidget(parent) {}
    void paintEvent(QPaintEvent *);
};

void RootWidget::paintEvent(QPaintEvent *e)
{
    QWidget::paintEvent(e);

    QPainter painter(this);
113 114 115 116 117 118
    QColor light = Utils::StyleHelper::mergedColors(
            palette().button().color(), Qt::white, 30);
    QColor dark = Utils::StyleHelper::mergedColors(
            palette().button().color(), Qt::black, 85);

    painter.setPen(light);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
119
    painter.drawLine(rect().topRight(), rect().bottomRight());
120
    painter.setPen(dark);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
121 122 123
    painter.drawLine(rect().topRight() - QPoint(1,0), rect().bottomRight() - QPoint(1,0));
}

124 125 126 127
///
// PanelsWidget
///

Tobias Hunger's avatar
Tobias Hunger committed
128 129
PanelsWidget::PanelsWidget(QWidget *parent) :
    QScrollArea(parent),
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
130
    m_root(new RootWidget(this))
dt's avatar
dt committed
131
{
132
    // We want a 900px wide widget with and the scrollbar at the
Tobias Hunger's avatar
Tobias Hunger committed
133
    // side of the screen.
134
    m_root->setFixedWidth(900);
135
    m_root->setContentsMargins(0, 0, 40, 0);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
136 137
    
    QPalette pal = m_root->palette();
138 139 140
    QColor background = Utils::StyleHelper::mergedColors(
            palette().window().color(), Qt::white, 85);
    pal.setColor(QPalette::All, QPalette::Window, background.darker(102));
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
141
    setPalette(pal);
142 143
    pal.setColor(QPalette::All, QPalette::Window, background);
    m_root->setPalette(pal);
Tobias Hunger's avatar
Tobias Hunger committed
144
    // The layout holding the individual panels:
Tobias Hunger's avatar
Tobias Hunger committed
145 146 147
    m_layout = new QGridLayout(m_root);
    m_layout->setColumnMinimumWidth(0, ICON_SIZE + 4);
    m_layout->setSpacing(0);
Tobias Hunger's avatar
Tobias Hunger committed
148

149
    setWidget(m_root);
dt's avatar
dt committed
150
    setFrameStyle(QFrame::NoFrame);
dt's avatar
dt committed
151
    setWidgetResizable(true);
dt's avatar
dt committed
152 153 154 155
}

PanelsWidget::~PanelsWidget()
{
con's avatar
con committed
156
    qDeleteAll(m_panels);
dt's avatar
dt committed
157 158
}

Tobias Hunger's avatar
Tobias Hunger committed
159 160 161 162 163
/*
 * Add a widget with heading information into the grid
 * layout of the PanelsWidget.
 *
 *     ...
Tobias Hunger's avatar
Tobias Hunger committed
164
 * +--------+-------------------------------------------+ ABOVE_HEADING_MARGIN
Tobias Hunger's avatar
Tobias Hunger committed
165 166
 * | icon   | name                                      |
 * +        +-------------------------------------------+
Tobias Hunger's avatar
Tobias Hunger committed
167 168 169 170
 * |        | line                                      |
 * +--------+-------------------------------------------+ ABOVE_CONTENTS_MARGIN
 * |          widget (with contentsmargins adjusted!)   |
 * +--------+-------------------------------------------+ BELOW_CONTENTS_MARGIN
Tobias Hunger's avatar
Tobias Hunger committed
171
 */
con's avatar
con committed
172
void PanelsWidget::addPropertiesPanel(IPropertiesPanel *panel)
dt's avatar
dt committed
173
{
con's avatar
con committed
174
    QTC_ASSERT(panel, return);
Tobias Hunger's avatar
Tobias Hunger committed
175

Tobias Hunger's avatar
Tobias Hunger committed
176 177 178
    const int headerRow(m_layout->rowCount() - 1);
    m_layout->setRowStretch(headerRow, 0);

Tobias Hunger's avatar
Tobias Hunger committed
179
    // icon:
con's avatar
con committed
180 181 182 183
    if (!panel->icon().isNull()) {
        QLabel *iconLabel = new QLabel(m_root);
        iconLabel->setPixmap(panel->icon().pixmap(ICON_SIZE, ICON_SIZE));
        iconLabel->setContentsMargins(0, ABOVE_HEADING_MARGIN, 0, 0);
con's avatar
con committed
184
        m_layout->addWidget(iconLabel, headerRow, 0, 3, 1, Qt::AlignTop | Qt::AlignHCenter);
Tobias Hunger's avatar
Tobias Hunger committed
185 186 187
    }

    // name:
con's avatar
con committed
188 189
    QLabel *nameLabel = new QLabel(m_root);
    nameLabel->setText(panel->displayName());
190 191 192
    QPalette palette = nameLabel->palette();
    palette.setBrush(QPalette::All, QPalette::Foreground, QColor(0, 0, 0, 110));
    nameLabel->setPalette(palette);
con's avatar
con committed
193 194
    nameLabel->setContentsMargins(0, ABOVE_HEADING_MARGIN, 0, 0);
    QFont f = nameLabel->font();
dt's avatar
dt committed
195
    f.setBold(true);
con's avatar
con committed
196
    f.setPointSizeF(f.pointSizeF() * 1.6);
con's avatar
con committed
197
    nameLabel->setFont(f);
con's avatar
con committed
198
    m_layout->addWidget(nameLabel, headerRow, 1, 1, 1, Qt::AlignVCenter | Qt::AlignLeft);
Tobias Hunger's avatar
Tobias Hunger committed
199 200 201

    // line:
    const int lineRow(headerRow + 1);
con's avatar
con committed
202 203
    QWidget *line = new OnePixelBlackLine(m_root);
    m_layout->addWidget(line, lineRow, 1, 1, -1, Qt::AlignTop);
Tobias Hunger's avatar
Tobias Hunger committed
204

Tobias Hunger's avatar
Tobias Hunger committed
205
    // add the widget:
Tobias Hunger's avatar
Tobias Hunger committed
206
    const int widgetRow(lineRow + 1);
con's avatar
con committed
207
    addPanelWidget(panel, widgetRow);
dt's avatar
dt committed
208 209
}

con's avatar
con committed
210
void PanelsWidget::addPanelWidget(IPropertiesPanel *panel, int row)
Tobias Hunger's avatar
Tobias Hunger committed
211
{
con's avatar
con committed
212
    QWidget *widget = panel->widget();
213
    widget->setContentsMargins(Constants::PANEL_LEFT_MARGIN,
Tobias Hunger's avatar
Tobias Hunger committed
214 215
                               ABOVE_CONTENTS_MARGIN, 0,
                               BELOW_CONTENTS_MARGIN);
con's avatar
con committed
216 217
    widget->setParent(m_root);
    m_layout->addWidget(widget, row, 0, 1, 2);
Tobias Hunger's avatar
Tobias Hunger committed
218 219 220 221 222 223 224

    const int stretchRow(row + 1);
    m_layout->setRowStretch(stretchRow, 10);

    m_panels.append(panel);
}

dt's avatar
dt committed
225 226 227 228
///
// ProjectWindow
///

dt's avatar
dt committed
229
ProjectWindow::ProjectWindow(QWidget *parent)
con's avatar
con committed
230
    : QWidget(parent),
231
    m_currentWidget(0)
con's avatar
con committed
232
{
233
    ProjectExplorer::SessionManager *session = ProjectExplorerPlugin::instance()->session();
con's avatar
con committed
234

Tobias Hunger's avatar
Tobias Hunger committed
235 236 237 238
    // Setup overall layout:
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);
dt's avatar
dt committed
239

con's avatar
con committed
240 241
    m_tabWidget = new DoubleTabWidget(this);
    viewLayout->addWidget(m_tabWidget);
242

Tobias Hunger's avatar
Tobias Hunger committed
243
    // Setup our container for the contents:
con's avatar
con committed
244 245
    m_centralWidget = new QStackedWidget(this);
    viewLayout->addWidget(m_centralWidget);
Tobias Hunger's avatar
Tobias Hunger committed
246 247

    // connects:
con's avatar
con committed
248 249
    connect(m_tabWidget, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(showProperties(int,int)));
dt's avatar
dt committed
250

251 252 253 254
    connect(session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus()));
    connect(session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus()));

    connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
255
            this, SLOT(registerProject(ProjectExplorer::Project*)));
con's avatar
con committed
256
    connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
257
            this, SLOT(deregisterProject(ProjectExplorer::Project*)));
258

259 260 261
    connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project *)));

262
    // Update properties to empty project for now:
con's avatar
con committed
263
    showProperties(-1, -1);
con's avatar
con committed
264 265 266 267 268 269
}

ProjectWindow::~ProjectWindow()
{
}

270
void ProjectWindow::aboutToShutdown()
271
{
con's avatar
con committed
272 273 274
    showProperties(-1, -1); // TODO that's a bit stupid, but otherwise stuff is still
                             // connected to the session
    disconnect(ProjectExplorerPlugin::instance()->session(), 0, this, 0);
275 276
}

277
void ProjectWindow::registerProject(ProjectExplorer::Project *project)
278
{
279
    if (!project || m_tabIndexToProject.contains(project))
Tobias Hunger's avatar
Tobias Hunger committed
280 281
        return;

282 283 284 285 286 287 288 289 290 291
    // find index to insert:
    int index = -1;
    for (int i = 0; i <= m_tabIndexToProject.count(); ++i) {
        if (i == m_tabIndexToProject.count() ||
            m_tabIndexToProject.at(i)->displayName() > project->displayName()) {
            index = i;
            break;
        }
    }

con's avatar
con committed
292
    QStringList subtabs;
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    if (project->supportedTargetIds().count() <= 1) {
        // Show the target specific pages directly
        QList<ITargetPanelFactory *> factories =
                ExtensionSystem::PluginManager::instance()->getObjects<ITargetPanelFactory>();

        foreach (ITargetPanelFactory *factory, factories) {
            if (factory->supports(project->activeTarget()))
                subtabs << factory->displayName();
        }
    } else {
        // Use the Targets page
        subtabs << QCoreApplication::translate("TargetSettingsPanelFactory", "Targets");
    }

    // Add the project specific pages

    QList<IProjectPanelFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<IProjectPanelFactory>();
    foreach (IProjectPanelFactory *panelFactory, factories) {
        if (panelFactory->supports(project))
            subtabs << panelFactory->displayName();
313
    }
Tobias Hunger's avatar
Tobias Hunger committed
314

con's avatar
con committed
315 316
    m_tabIndexToProject.insert(index, project);
    m_tabWidget->insertTab(index, project->displayName(), subtabs);
317 318 319

    connect(project, SIGNAL(supportedTargetIdsChanged()),
            this, SLOT(refreshProject()));
con's avatar
con committed
320 321
}

322
void ProjectWindow::deregisterProject(ProjectExplorer::Project *project)
con's avatar
con committed
323 324
{
    int index = m_tabIndexToProject.indexOf(project);
325 326
    if (index < 0)
        return;
327 328 329 330

    disconnect(project, SIGNAL(supportedTargetIdsChanged()),
               this, SLOT(refreshProject()));

con's avatar
con committed
331 332
    m_tabIndexToProject.removeAt(index);
    m_tabWidget->removeTab(index);
333 334
}

con's avatar
con committed
335 336
void ProjectWindow::restoreStatus()
{
dt's avatar
dt committed
337
    // TODO
con's avatar
con committed
338 339 340 341
}

void ProjectWindow::saveStatus()
{
dt's avatar
dt committed
342
    // TODO
con's avatar
con committed
343 344
}

345 346 347 348 349 350
void ProjectWindow::refreshProject()
{
    Project *project = qobject_cast<ProjectExplorer::Project *>(sender());
    if (!m_tabIndexToProject.contains(project))
        return;

351 352
    // TODO this changes the subindex
    int index = m_tabWidget->currentIndex();
353 354
    deregisterProject(project);
    registerProject(project);
355 356 357 358 359 360
    m_tabWidget->setCurrentIndex(index);
}

void ProjectWindow::startupProjectChanged(ProjectExplorer::Project *p)
{
    int index = m_tabIndexToProject.indexOf(p);
361 362
    if (index != -1)
        m_tabWidget->setCurrentIndex(index);
363 364
}

con's avatar
con committed
365
void ProjectWindow::showProperties(int index, int subIndex)
con's avatar
con committed
366
{
367
    if (index < 0 || index >= m_tabIndexToProject.count())
con's avatar
con committed
368
        return;
369

con's avatar
con committed
370
    Project *project = m_tabIndexToProject.at(index);
dt's avatar
dt committed
371

372
    // Set up custom panels again:
Tobias Hunger's avatar
Tobias Hunger committed
373
    int pos = 0;
374 375 376 377
    IPanelFactory *fac = 0;
    if (project->supportedTargetIds().count() > 1) {
        if (subIndex == 0) {
            // Targets page
Tobias Hunger's avatar
Tobias Hunger committed
378
            removeCurrentWidget();
379
            m_currentWidget = new TargetSettingsPanelWidget(project);
Tobias Hunger's avatar
Tobias Hunger committed
380 381
            m_centralWidget->addWidget(m_currentWidget);
            m_centralWidget->setCurrentWidget(m_currentWidget);
con's avatar
con committed
382
        }
Tobias Hunger's avatar
Tobias Hunger committed
383
        ++pos;
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
    } else {
        // No Targets page, target specific pages are first in the list
        foreach (ITargetPanelFactory *panelFactory, ExtensionSystem::PluginManager::instance()->getObjects<ITargetPanelFactory>()) {
            if (panelFactory->supports(project->activeTarget())) {
                if (subIndex == pos) {
                    fac = panelFactory;
                    break;
                }
                ++pos;
            }
        }
    }

    if (!fac) {
        foreach (IProjectPanelFactory *panelFactory, ExtensionSystem::PluginManager::instance()->getObjects<IProjectPanelFactory>()) {
            if (panelFactory->supports(project)) {
                if (subIndex == pos) {
                    fac = panelFactory;
                    break;
                }
                ++pos;
            }
        }
con's avatar
con committed
407
    }
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

    if (fac) {
        removeCurrentWidget();

        IPropertiesPanel *panel;
        if (ITargetPanelFactory *ipf = qobject_cast<ITargetPanelFactory *>(fac))
            panel = ipf->createPanel(project->activeTarget());
        else if (IProjectPanelFactory *ipf = qobject_cast<IProjectPanelFactory *>(fac))
            panel = ipf->createPanel(project);
        Q_ASSERT(panel);

        PanelsWidget *panelsWidget = new PanelsWidget(m_centralWidget);
        panelsWidget->addPropertiesPanel(panel);
        m_currentWidget = panelsWidget;
        m_centralWidget->addWidget(m_currentWidget);
        m_centralWidget->setCurrentWidget(m_currentWidget);

    }

427
    ProjectExplorerPlugin::instance()->session()->setStartupProject(project);
Tobias Hunger's avatar
Tobias Hunger committed
428 429 430 431 432 433
}

void ProjectWindow::removeCurrentWidget()
{
    if (m_currentWidget) {
        m_centralWidget->removeWidget(m_currentWidget);
434
        if (m_currentWidget) {
Tobias Hunger's avatar
Tobias Hunger committed
435 436
            delete m_currentWidget;
            m_currentWidget = 0;
con's avatar
con committed
437 438 439
        }
    }
}