projectwindow.cpp 14.2 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.nokia.com.
con's avatar
con committed
30
**
31
**************************************************************************/
hjk's avatar
hjk committed
32

con's avatar
con committed
33
#include "projectwindow.h"
hjk's avatar
hjk committed
34

con's avatar
con committed
35 36
#include "doubletabwidget.h"

hjk's avatar
hjk committed
37
#include "project.h"
con's avatar
con committed
38 39 40 41
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "session.h"
#include "projecttreewidget.h"
42
#include "iprojectproperties.h"
Tobias Hunger's avatar
Tobias Hunger committed
43
#include "targetsettingspanel.h"
44
#include "target.h"
con's avatar
con committed
45 46

#include <coreplugin/icore.h>
47
#include <coreplugin/ifile.h>
48
#include <extensionsystem/pluginmanager.h>
Tobias Hunger's avatar
Tobias Hunger committed
49
#include <utils/qtcassert.h>
50
#include <utils/stylehelper.h>
con's avatar
con committed
51

52
#include <QtGui/QApplication>
53
#include <QtGui/QGridLayout>
dt's avatar
dt committed
54
#include <QtGui/QLabel>
dt's avatar
dt committed
55
#include <QtGui/QPainter>
56
#include <QtGui/QStackedWidget>
57

con's avatar
con committed
58 59 60 61
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace {
Tobias Hunger's avatar
Tobias Hunger committed
62
const int ICON_SIZE(64);
Tobias Hunger's avatar
Tobias Hunger committed
63 64 65 66

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
67

68
} // anonymous namespace
Tobias Hunger's avatar
Tobias Hunger committed
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
///
// 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
86
        Q_UNUSED(e);
87
        QPainter p(this);
88 89 90
        QColor fillColor = Utils::StyleHelper::mergedColors(
                palette().button().color(), Qt::black, 80);
        p.fillRect(contentsRect(), fillColor);
91 92 93
    }
};

Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
94 95 96 97 98 99 100 101 102 103 104 105
class RootWidget : public QWidget
{
public:
    RootWidget(QWidget *parent) : QWidget(parent) {}
    void paintEvent(QPaintEvent *);
};

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

    QPainter painter(this);
106 107 108 109 110 111
    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
112
    painter.drawLine(rect().topRight(), rect().bottomRight());
113
    painter.setPen(dark);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
114 115 116
    painter.drawLine(rect().topRight() - QPoint(1,0), rect().bottomRight() - QPoint(1,0));
}

117 118 119 120
///
// PanelsWidget
///

Tobias Hunger's avatar
Tobias Hunger committed
121 122
PanelsWidget::PanelsWidget(QWidget *parent) :
    QScrollArea(parent),
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
123
    m_root(new RootWidget(this))
dt's avatar
dt committed
124
{
125
    // We want a 900px wide widget with and the scrollbar at the
Tobias Hunger's avatar
Tobias Hunger committed
126
    // side of the screen.
127
    m_root->setFixedWidth(900);
128
    m_root->setContentsMargins(0, 0, 40, 0);
Jens Bache-Wiig's avatar
Jens Bache-Wiig committed
129 130
    
    QPalette pal = m_root->palette();
131 132 133
    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
134
    setPalette(pal);
135 136
    pal.setColor(QPalette::All, QPalette::Window, background);
    m_root->setPalette(pal);
Tobias Hunger's avatar
Tobias Hunger committed
137
    // The layout holding the individual panels:
Tobias Hunger's avatar
Tobias Hunger committed
138 139 140
    m_layout = new QGridLayout(m_root);
    m_layout->setColumnMinimumWidth(0, ICON_SIZE + 4);
    m_layout->setSpacing(0);
Tobias Hunger's avatar
Tobias Hunger committed
141

142
    setWidget(m_root);
dt's avatar
dt committed
143
    setFrameStyle(QFrame::NoFrame);
dt's avatar
dt committed
144
    setWidgetResizable(true);
dt's avatar
dt committed
145 146 147 148
}

PanelsWidget::~PanelsWidget()
{
con's avatar
con committed
149
    qDeleteAll(m_panels);
dt's avatar
dt committed
150 151
}

Tobias Hunger's avatar
Tobias Hunger committed
152 153 154 155 156
/*
 * Add a widget with heading information into the grid
 * layout of the PanelsWidget.
 *
 *     ...
Tobias Hunger's avatar
Tobias Hunger committed
157
 * +--------+-------------------------------------------+ ABOVE_HEADING_MARGIN
Tobias Hunger's avatar
Tobias Hunger committed
158 159
 * | icon   | name                                      |
 * +        +-------------------------------------------+
Tobias Hunger's avatar
Tobias Hunger committed
160 161 162 163
 * |        | line                                      |
 * +--------+-------------------------------------------+ ABOVE_CONTENTS_MARGIN
 * |          widget (with contentsmargins adjusted!)   |
 * +--------+-------------------------------------------+ BELOW_CONTENTS_MARGIN
Tobias Hunger's avatar
Tobias Hunger committed
164
 */
165
void PanelsWidget::addPropertiesPanel(PropertiesPanel *panel)
dt's avatar
dt committed
166
{
con's avatar
con committed
167
    QTC_ASSERT(panel, return);
Tobias Hunger's avatar
Tobias Hunger committed
168

Tobias Hunger's avatar
Tobias Hunger committed
169 170
    const int headerRow(m_layout->rowCount() - 1);

Tobias Hunger's avatar
Tobias Hunger committed
171
    // icon:
con's avatar
con committed
172 173 174 175
    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
176
        m_layout->addWidget(iconLabel, headerRow, 0, 3, 1, Qt::AlignTop | Qt::AlignHCenter);
Tobias Hunger's avatar
Tobias Hunger committed
177 178 179
    }

    // name:
con's avatar
con committed
180 181
    QLabel *nameLabel = new QLabel(m_root);
    nameLabel->setText(panel->displayName());
182 183 184
    QPalette palette = nameLabel->palette();
    palette.setBrush(QPalette::All, QPalette::Foreground, QColor(0, 0, 0, 110));
    nameLabel->setPalette(palette);
con's avatar
con committed
185 186
    nameLabel->setContentsMargins(0, ABOVE_HEADING_MARGIN, 0, 0);
    QFont f = nameLabel->font();
dt's avatar
dt committed
187
    f.setBold(true);
con's avatar
con committed
188
    f.setPointSizeF(f.pointSizeF() * 1.6);
con's avatar
con committed
189
    nameLabel->setFont(f);
con's avatar
con committed
190
    m_layout->addWidget(nameLabel, headerRow, 1, 1, 1, Qt::AlignVCenter | Qt::AlignLeft);
Tobias Hunger's avatar
Tobias Hunger committed
191 192 193

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

Tobias Hunger's avatar
Tobias Hunger committed
197
    // add the widget:
Tobias Hunger's avatar
Tobias Hunger committed
198
    const int widgetRow(lineRow + 1);
con's avatar
con committed
199
    addPanelWidget(panel, widgetRow);
dt's avatar
dt committed
200 201
}

202
void PanelsWidget::addPanelWidget(PropertiesPanel *panel, int row)
Tobias Hunger's avatar
Tobias Hunger committed
203
{
con's avatar
con committed
204
    QWidget *widget = panel->widget();
205
    widget->setContentsMargins(Constants::PANEL_LEFT_MARGIN,
Tobias Hunger's avatar
Tobias Hunger committed
206 207
                               ABOVE_CONTENTS_MARGIN, 0,
                               BELOW_CONTENTS_MARGIN);
con's avatar
con committed
208 209
    widget->setParent(m_root);
    m_layout->addWidget(widget, row, 0, 1, 2);
Tobias Hunger's avatar
Tobias Hunger committed
210 211 212 213

    m_panels.append(panel);
}

dt's avatar
dt committed
214 215 216 217
///
// ProjectWindow
///

dt's avatar
dt committed
218
ProjectWindow::ProjectWindow(QWidget *parent)
con's avatar
con committed
219
    : QWidget(parent),
220 221
      m_currentWidget(0),
      m_previousTargetSubIndex(-1)
con's avatar
con committed
222
{
223
    ProjectExplorer::SessionManager *session = ProjectExplorerPlugin::instance()->session();
con's avatar
con committed
224

Tobias Hunger's avatar
Tobias Hunger committed
225 226 227 228
    // Setup overall layout:
    QVBoxLayout *viewLayout = new QVBoxLayout(this);
    viewLayout->setMargin(0);
    viewLayout->setSpacing(0);
dt's avatar
dt committed
229

con's avatar
con committed
230 231
    m_tabWidget = new DoubleTabWidget(this);
    viewLayout->addWidget(m_tabWidget);
232

Tobias Hunger's avatar
Tobias Hunger committed
233
    // Setup our container for the contents:
con's avatar
con committed
234 235
    m_centralWidget = new QStackedWidget(this);
    viewLayout->addWidget(m_centralWidget);
Tobias Hunger's avatar
Tobias Hunger committed
236 237

    // connects:
con's avatar
con committed
238 239
    connect(m_tabWidget, SIGNAL(currentIndexChanged(int,int)),
            this, SLOT(showProperties(int,int)));
dt's avatar
dt committed
240

241 242 243 244
    connect(session, SIGNAL(sessionLoaded()), this, SLOT(restoreStatus()));
    connect(session, SIGNAL(aboutToSaveSession()), this, SLOT(saveStatus()));

    connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
245
            this, SLOT(registerProject(ProjectExplorer::Project*)));
con's avatar
con committed
246
    connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
247
            this, SLOT(deregisterProject(ProjectExplorer::Project*)));
248

249 250 251
    connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
            this, SLOT(startupProjectChanged(ProjectExplorer::Project *)));

252
    // Update properties to empty project for now:
con's avatar
con committed
253
    showProperties(-1, -1);
con's avatar
con committed
254 255 256 257 258 259
}

ProjectWindow::~ProjectWindow()
{
}

260 261 262 263 264 265 266 267
void ProjectWindow::extensionsInitialized()
{
    foreach (ITargetFactory *fac, ExtensionSystem::PluginManager::instance()->getObjects<ITargetFactory>())
        connect(fac, SIGNAL(supportedTargetIdsChanged()),
                this, SLOT(targetFactoriesChanged()));

}

268
void ProjectWindow::aboutToShutdown()
269
{
con's avatar
con committed
270 271 272
    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);
273 274
}

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
void ProjectWindow::targetFactoriesChanged()
{
    bool changed = false;
    int index = m_tabWidget->currentIndex();
    QList<Project *> projects = m_tabIndexToProject;
    foreach (ProjectExplorer::Project *project, projects) {
        if (m_usesTargetPage.value(project) != useTargetPage(project)) {
            changed = true;
            deregisterProject(project);
            registerProject(project);
        }
    }
    if (changed)
        m_tabWidget->setCurrentIndex(index);
}

bool ProjectWindow::useTargetPage(ProjectExplorer::Project *project)
{
    if (project->targets().size() > 1)
        return true;
    QStringList tmp;
    foreach (ITargetFactory *fac, ExtensionSystem::PluginManager::instance()->getObjects<ITargetFactory>()) {
        tmp.append(fac->supportedTargetIds(project));
        if (tmp.size() > 1)
            return true;
    }
    return false;
}

304
void ProjectWindow::registerProject(ProjectExplorer::Project *project)
305
{
306
    if (!project || m_tabIndexToProject.contains(project))
Tobias Hunger's avatar
Tobias Hunger committed
307 308
        return;

309 310 311 312 313 314 315 316 317 318
    // 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
319
    QStringList subtabs;
320 321 322 323 324

    bool usesTargetPage = useTargetPage(project);
    m_usesTargetPage.insert(project, usesTargetPage);

    if (!usesTargetPage){
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
        // 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();
344
    }
Tobias Hunger's avatar
Tobias Hunger committed
345

con's avatar
con committed
346
    m_tabIndexToProject.insert(index, project);
dt's avatar
dt committed
347
    m_tabWidget->insertTab(index, project->displayName(), project->file()->fileName(), subtabs);
con's avatar
con committed
348 349
}

350
void ProjectWindow::deregisterProject(ProjectExplorer::Project *project)
con's avatar
con committed
351 352
{
    int index = m_tabIndexToProject.indexOf(project);
353 354
    if (index < 0)
        return;
355

con's avatar
con committed
356 357
    m_tabIndexToProject.removeAt(index);
    m_tabWidget->removeTab(index);
358 359
}

con's avatar
con committed
360 361
void ProjectWindow::restoreStatus()
{
dt's avatar
dt committed
362
    // TODO
con's avatar
con committed
363 364 365 366
}

void ProjectWindow::saveStatus()
{
dt's avatar
dt committed
367
    // TODO
con's avatar
con committed
368 369
}

370 371 372
void ProjectWindow::startupProjectChanged(ProjectExplorer::Project *p)
{
    int index = m_tabIndexToProject.indexOf(p);
373 374
    if (index != -1)
        m_tabWidget->setCurrentIndex(index);
375 376
}

con's avatar
con committed
377
void ProjectWindow::showProperties(int index, int subIndex)
con's avatar
con committed
378
{
379 380
    if (index < 0 || index >= m_tabIndexToProject.count()) {
        removeCurrentWidget();
con's avatar
con committed
381
        return;
382
    }
383

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

386
    // Set up custom panels again:
Tobias Hunger's avatar
Tobias Hunger committed
387
    int pos = 0;
388
    IPanelFactory *fac = 0;
389 390 391 392 393
    // remember previous sub index state of target settings page
    if (TargetSettingsPanelWidget *previousPanelWidget
            = qobject_cast<TargetSettingsPanelWidget*>(m_currentWidget)) {
        m_previousTargetSubIndex = previousPanelWidget->currentSubIndex();
    }
394 395

    if (m_usesTargetPage.value(project)) {
396 397
        if (subIndex == 0) {
            // Targets page
Tobias Hunger's avatar
Tobias Hunger committed
398
            removeCurrentWidget();
399 400 401 402
            TargetSettingsPanelWidget *panelWidget = new TargetSettingsPanelWidget(project);
            if (m_previousTargetSubIndex >= 0)
                panelWidget->setCurrentSubIndex(m_previousTargetSubIndex);
            m_currentWidget = panelWidget;
Tobias Hunger's avatar
Tobias Hunger committed
403 404
            m_centralWidget->addWidget(m_currentWidget);
            m_centralWidget->setCurrentWidget(m_currentWidget);
con's avatar
con committed
405
        }
Tobias Hunger's avatar
Tobias Hunger committed
406
        ++pos;
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
    } 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
430
    }
431 432 433 434

    if (fac) {
        removeCurrentWidget();

435
        PropertiesPanel *panel = 0;
436 437 438 439 440 441 442 443 444 445 446 447 448 449
        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);

    }

450
    ProjectExplorerPlugin::instance()->session()->setStartupProject(project);
Tobias Hunger's avatar
Tobias Hunger committed
451 452 453 454 455 456
}

void ProjectWindow::removeCurrentWidget()
{
    if (m_currentWidget) {
        m_centralWidget->removeWidget(m_currentWidget);
457
        if (m_currentWidget) {
Tobias Hunger's avatar
Tobias Hunger committed
458 459
            delete m_currentWidget;
            m_currentWidget = 0;
con's avatar
con committed
460 461 462
        }
    }
}