OSDN Git Service

9c81adcf6bd1660d37b7ad2476642d82621914ce
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmldesigner / designmodewidget.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "designmodewidget.h"
35 #include "qmldesignerconstants.h"
36 #include "styledoutputpaneplaceholder.h"
37 #include "designmodecontext.h"
38
39 #include <model.h>
40 #include <rewriterview.h>
41 #include <formeditorwidget.h>
42 #include <stateseditorwidget.h>
43 #include <itemlibrarywidget.h>
44
45
46 #include <coreplugin/coreconstants.h>
47 #include <coreplugin/modemanager.h>
48 #include <coreplugin/outputpane.h>
49 #include <coreplugin/icore.h>
50 #include <coreplugin/minisplitter.h>
51 #include <coreplugin/sidebar.h>
52 #include <coreplugin/editormanager/editormanager.h>
53 #include <coreplugin/editormanager/openeditorsmodel.h>
54 #include <coreplugin/editormanager/ieditor.h>
55 #include <coreplugin/editortoolbar.h>
56 #include <coreplugin/inavigationwidgetfactory.h>
57 #include <extensionsystem/pluginmanager.h>
58
59 #include <utils/parameteraction.h>
60 #include <utils/qtcassert.h>
61
62 #include <QtCore/QSettings>
63 #include <QtCore/QEvent>
64 #include <QtCore/QDir>
65 #include <QtGui/QApplication>
66 #include <QtGui/QPlainTextEdit>
67 #include <QtGui/QVBoxLayout>
68 #include <QtGui/QScrollArea>
69 #include <QtGui/QTabWidget>
70 #include <QtGui/QToolButton>
71 #include <QtGui/QMenu>
72 #include <QtGui/QClipboard>
73 #include <QtGui/QLabel>
74 #include <QtGui/QProgressDialog>
75
76 using Core::MiniSplitter;
77 using Core::IEditor;
78 using Core::EditorManager;
79
80 using namespace QmlDesigner;
81
82 enum {
83     debug = false
84 };
85
86 const char * const SB_NAVIGATOR = "Navigator";
87 const char * const SB_LIBRARY = "Library";
88 const char * const SB_PROPERTIES = "Properties";
89 const char * const SB_PROJECTS = "Projects";
90 const char * const SB_FILESYSTEM = "FileSystem";
91 const char * const SB_OPENDOCUMENTS = "OpenDocuments";
92
93 namespace QmlDesigner {
94 namespace Internal {
95
96 DocumentWarningWidget::DocumentWarningWidget(DesignModeWidget *parent) :
97         Utils::FakeToolTip(parent),
98         m_errorMessage(new QLabel("Placeholder", this)),
99         m_goToError(new QLabel(this)),
100         m_designModeWidget(parent)
101 {
102     setWindowFlags(Qt::Widget); //We only want the visual style from a ToolTip
103     setForegroundRole(QPalette::ToolTipText);
104     setBackgroundRole(QPalette::ToolTipBase);
105     setAutoFillBackground(true);
106
107     m_errorMessage->setForegroundRole(QPalette::ToolTipText);
108     m_goToError->setText(tr("<a href=\"goToError\">Go to error</a>"));
109     m_goToError->setForegroundRole(QPalette::Link);
110     connect(m_goToError, SIGNAL(linkActivated(QString)), this, SLOT(goToError()));
111
112     QVBoxLayout *layout = new QVBoxLayout(this);
113     layout->setMargin(20);
114     layout->setSpacing(5);
115     layout->addWidget(m_errorMessage);
116     layout->addWidget(m_goToError, 1, Qt::AlignRight);
117 }
118
119 void DocumentWarningWidget::setError(const RewriterView::Error &error)
120 {
121     m_error = error;
122     QString str;
123     if (error.type() == RewriterView::Error::ParseError) {
124         str = tr("%3 (%1:%2)").arg(QString::number(error.line()), QString::number(error.column()), error.description());
125         m_goToError->show();
126     }  else if (error.type() == RewriterView::Error::InternalError) {
127         str = tr("Internal error (%1)").arg(error.description());
128         m_goToError->hide();
129     }
130
131     m_errorMessage->setText(str);
132     resize(layout()->totalSizeHint());
133 }
134
135 class ItemLibrarySideBarItem : public Core::SideBarItem
136 {
137 public:
138     explicit ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id);
139     virtual ~ItemLibrarySideBarItem();
140
141     virtual QList<QToolButton *> createToolBarWidgets();
142 };
143
144 ItemLibrarySideBarItem::ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {}
145
146 ItemLibrarySideBarItem::~ItemLibrarySideBarItem()
147 {
148
149 }
150
151 QList<QToolButton *> ItemLibrarySideBarItem::createToolBarWidgets()
152 {
153     return qobject_cast<ItemLibraryWidget*>(widget())->createToolBarWidgets();
154 }
155
156 void DocumentWarningWidget::goToError()
157 {
158     m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column() - 1);
159     Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
160 }
161
162 // ---------- DesignModeWidget
163 DesignModeWidget::DesignModeWidget(QWidget *parent) :
164     QWidget(parent),
165     m_syncWithTextEdit(false),
166     m_mainSplitter(0),
167     m_leftSideBar(0),
168     m_rightSideBar(0),
169     m_isDisabled(false),
170     m_showSidebars(true),
171     m_initStatus(NotInitialized),
172     m_warningWidget(0)
173 {
174     m_undoAction = new QAction(tr("&Undo"), this);
175     connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
176     m_redoAction = new QAction(tr("&Redo"), this);
177     connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo()));
178     m_deleteAction = new Utils::ParameterAction(tr("Delete"), tr("Delete \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
179     connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelected()));
180     m_cutAction = new Utils::ParameterAction(tr("Cu&t"), tr("Cut \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
181     connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cutSelected()));
182     m_copyAction = new Utils::ParameterAction(tr("&Copy"), tr("Copy \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
183     connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copySelected()));
184     m_pasteAction = new Utils::ParameterAction(tr("&Paste"), tr("Paste \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
185     connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste()));
186     m_selectAllAction = new Utils::ParameterAction(tr("Select &All"), tr("Select All \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
187     connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll()));
188     m_hideSidebarsAction = new QAction(tr("Toggle Full Screen"), this);
189     connect(m_hideSidebarsAction, SIGNAL(triggered()), this, SLOT(toggleSidebars()));
190     m_restoreDefaultViewAction = new QAction(tr("&Restore Default View"), this);
191     connect(m_restoreDefaultViewAction, SIGNAL(triggered()), SLOT(restoreDefaultView()));
192     m_toggleLeftSidebarAction = new QAction(tr("Toggle &Left Sidebar"), this);
193     connect(m_toggleLeftSidebarAction, SIGNAL(triggered()), SLOT(toggleLeftSidebar()));
194     m_toggleRightSidebarAction = new QAction(tr("Toggle &Right Sidebar"), this);
195     connect(m_toggleRightSidebarAction, SIGNAL(triggered()), SLOT(toggleRightSidebar()));
196
197     Core::ModeManager *modeManager = Core::ModeManager::instance();
198     Core::IMode *designmode = modeManager->mode(Core::Constants::MODE_DESIGN);
199     m_outputPlaceholderSplitter = new Core::MiniSplitter;
200     m_outputPanePlaceholder = new StyledOutputpanePlaceHolder(designmode, m_outputPlaceholderSplitter);
201 }
202
203 DesignModeWidget::~DesignModeWidget()
204 {
205 }
206
207 void DesignModeWidget::restoreDefaultView()
208 {
209     QSettings *settings = Core::ICore::instance()->settings();
210     m_leftSideBar->closeAllWidgets();
211     m_rightSideBar->closeAllWidgets();
212     m_leftSideBar->readSettings(settings,  "none.LeftSideBar");
213     m_rightSideBar->readSettings(settings, "none.RightSideBar");
214     m_leftSideBar->show();
215     m_rightSideBar->show();
216 }
217
218 void DesignModeWidget::toggleLeftSidebar()
219 {
220     if (m_leftSideBar)
221         m_leftSideBar->setVisible(!m_leftSideBar->isVisible());
222 }
223
224 void DesignModeWidget::toggleRightSidebar()
225 {
226     if (m_rightSideBar)
227         m_rightSideBar->setVisible(!m_rightSideBar->isVisible());
228 }
229
230 void DesignModeWidget::toggleSidebars()
231 {
232     if (m_initStatus == Initializing)
233         return;
234
235     m_showSidebars = !m_showSidebars;
236
237     if (m_leftSideBar)
238         m_leftSideBar->setVisible(m_showSidebars);
239     if (m_rightSideBar)
240         m_rightSideBar->setVisible(m_showSidebars);
241     if (!m_statesEditorView.isNull())
242         m_statesEditorView->widget()->setVisible(m_showSidebars);
243
244 }
245
246 void DesignModeWidget::showEditor(Core::IEditor *editor)
247 {
248     //
249     // Prevent recursive calls to function by explicitly managing initialization status
250     // (QApplication::processEvents is called explicitly at a number of places)
251     //
252     if (m_initStatus == Initializing)
253         return;
254
255     if (m_initStatus == NotInitialized) {
256         m_initStatus = Initializing;
257         setup();
258     }
259
260     QString fileName;
261     QPlainTextEdit *textEdit = 0;
262     TextEditor::ITextEditor *textEditor = 0;
263
264     if (editor) {
265         fileName = editor->file()->fileName();
266         textEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
267         textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
268         if (textEditor)
269             m_fakeToolBar->addEditor(textEditor);
270     }
271
272     if (debug)
273         qDebug() << Q_FUNC_INFO << fileName;
274
275     if (textEdit)
276         m_currentTextEdit = textEdit;
277
278     if (textEditor)
279         m_textEditor = textEditor;
280     DesignDocumentController *document = 0;
281
282     if (textEdit && textEditor && fileName.endsWith(QLatin1String(".qml"))) {
283         if (m_documentHash.contains(textEdit)) {
284             document = m_documentHash.value(textEdit).data();
285         } else {
286             DesignDocumentController *newDocument = new DesignDocumentController(this);
287
288             newDocument->setNodeInstanceView(m_nodeInstanceView.data());
289             newDocument->setAllPropertiesBox(m_allPropertiesBox.data());
290             newDocument->setNavigator(m_navigator.data());
291             newDocument->setStatesEditorView(m_statesEditorView.data());
292             newDocument->setItemLibraryView(m_itemLibraryView.data());
293             newDocument->setFormEditorView(m_formEditorView.data());
294
295
296             newDocument->setFileName(fileName);
297
298             document = newDocument;          
299
300             m_documentHash.insert(textEdit, document);
301         }
302     }
303     setCurrentDocument(document);
304
305     m_initStatus = Initialized;
306 }
307
308 void DesignModeWidget::closeEditors(QList<Core::IEditor*> editors)
309 {
310     foreach (Core::IEditor* editor, editors) {
311         if (QPlainTextEdit *textEdit = qobject_cast<QPlainTextEdit*>(editor->widget())) {
312             if (m_currentTextEdit.data() == textEdit) {
313                 setCurrentDocument(0);
314             }
315             if (m_documentHash.contains(textEdit)) {
316                 if (debug)
317                     qDebug() << Q_FUNC_INFO << editor->file()->fileName();
318                 DesignDocumentController *document = m_documentHash.take(textEdit).data();
319                 delete document;
320             }
321         }
322     }
323 }
324
325 QAction *DesignModeWidget::undoAction() const
326 {
327     return m_undoAction;
328 }
329
330 QAction *DesignModeWidget::redoAction() const
331 {
332     return m_redoAction;
333 }
334
335 QAction *DesignModeWidget::deleteAction() const
336 {
337     return m_deleteAction;
338 }
339
340 QAction *DesignModeWidget::cutAction() const
341 {
342     return m_cutAction;
343 }
344
345 QAction *DesignModeWidget::copyAction() const
346 {
347     return m_copyAction;
348 }
349
350 QAction *DesignModeWidget::pasteAction() const
351 {
352     return m_pasteAction;
353 }
354
355 QAction *DesignModeWidget::selectAllAction() const
356 {
357     return m_selectAllAction;
358 }
359
360 QAction *DesignModeWidget::hideSidebarsAction() const
361 {
362     return m_hideSidebarsAction;
363 }
364
365 QAction *DesignModeWidget::toggleLeftSidebarAction() const
366 {
367     return m_toggleLeftSidebarAction;
368 }
369
370 QAction *DesignModeWidget::toggleRightSidebarAction() const
371 {
372     return m_toggleRightSidebarAction;
373 }
374
375
376 QAction *DesignModeWidget::restoreDefaultViewAction() const
377 {
378     return m_restoreDefaultViewAction;
379 }
380
381 void DesignModeWidget::readSettings()
382 {
383     QSettings *settings = Core::ICore::instance()->settings();
384
385     settings->beginGroup("Bauhaus");
386     m_leftSideBar->readSettings(settings, QLatin1String("LeftSideBar"));
387     m_rightSideBar->readSettings(settings, QLatin1String("RightSideBar"));
388     if (settings->contains("MainSplitter")) {
389         const QByteArray splitterState = settings->value("MainSplitter").toByteArray();
390         m_mainSplitter->restoreState(splitterState);
391         m_mainSplitter->setOpaqueResize(); // force opaque resize since it used to be off
392     }
393     settings->endGroup();
394 }
395
396 void DesignModeWidget::saveSettings()
397 {
398     QSettings *settings = Core::ICore::instance()->settings();
399
400     settings->beginGroup("Bauhaus");
401     m_leftSideBar->saveSettings(settings, QLatin1String("LeftSideBar"));
402     m_rightSideBar->saveSettings(settings, QLatin1String("RightSideBar"));
403     settings->setValue("MainSplitter", m_mainSplitter->saveState());
404     settings->endGroup();
405 }
406
407 void DesignModeWidget::undo()
408 {
409     if (m_currentDesignDocumentController)
410         m_currentDesignDocumentController->undo();
411 }
412
413 void DesignModeWidget::redo()
414 {
415     if (m_currentDesignDocumentController)
416         m_currentDesignDocumentController->redo();
417 }
418
419 void DesignModeWidget::deleteSelected()
420 {
421     if (m_currentDesignDocumentController)
422         m_currentDesignDocumentController->deleteSelected();
423 }
424
425 void DesignModeWidget::cutSelected()
426 {
427     if (m_currentDesignDocumentController)
428         m_currentDesignDocumentController->cutSelected();
429 }
430
431 void DesignModeWidget::copySelected()
432 {
433     if (m_currentDesignDocumentController)
434         m_currentDesignDocumentController->copySelected();
435 }
436
437 void DesignModeWidget::paste()
438 {
439     if (m_currentDesignDocumentController)
440         m_currentDesignDocumentController->paste();
441 }
442
443 void DesignModeWidget::selectAll()
444 {
445     if (m_currentDesignDocumentController)
446         m_currentDesignDocumentController->selectAll();
447 }
448
449 void DesignModeWidget::closeCurrentEditor()
450 {
451 }
452
453 void DesignModeWidget::undoAvailable(bool isAvailable)
454 {
455     DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
456     if (m_currentDesignDocumentController &&
457         m_currentDesignDocumentController.data() == documentController) {
458         m_undoAction->setEnabled(isAvailable);
459     }
460 }
461
462 void DesignModeWidget::redoAvailable(bool isAvailable)
463 {
464     DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
465     if (m_currentDesignDocumentController &&
466         m_currentDesignDocumentController.data() == documentController) {
467         m_redoAction->setEnabled(isAvailable);
468     }
469 }
470
471
472 void DesignModeWidget::enable()
473 {
474     if (debug)
475         qDebug() << Q_FUNC_INFO;
476     m_warningWidget->setVisible(false);
477     m_formEditorView->widget()->setEnabled(true);
478     m_statesEditorView->widget()->setEnabled(true);
479     m_leftSideBar->setEnabled(true);
480     m_rightSideBar->setEnabled(true);
481     m_isDisabled = false;
482 }
483
484 void DesignModeWidget::disable(const QList<RewriterView::Error> &errors)
485 {
486     if (debug)
487         qDebug() << Q_FUNC_INFO;
488     Q_ASSERT(!errors.isEmpty());
489     m_warningWidget->setError(errors.first());
490     m_warningWidget->setVisible(true);
491     m_warningWidget->move(width() / 2, height() / 2);
492     m_formEditorView->widget()->setEnabled(false);
493     m_statesEditorView->widget()->setEnabled(false);
494     m_leftSideBar->setEnabled(false);
495     m_rightSideBar->setEnabled(false);
496     m_isDisabled = true;
497 }
498
499 void DesignModeWidget::updateErrorStatus(const QList<RewriterView::Error> &errors)
500 {
501     if (debug)
502         qDebug() << Q_FUNC_INFO << errors.count();
503
504     if (m_isDisabled && errors.isEmpty()) {
505         enable();
506     } else if (!errors.isEmpty()) {
507         disable(errors);
508     }
509 }
510
511 void DesignModeWidget::setAutoSynchronization(bool sync)
512 {
513     if (debug)
514         qDebug() << Q_FUNC_INFO << sync;
515
516     m_currentDesignDocumentController->blockModelSync(!sync);
517
518     if (sync) {
519         // text editor -> visual editor
520         if (!m_currentDesignDocumentController->model()) {
521             m_currentDesignDocumentController->loadMaster(m_currentTextEdit.data());
522         } else {
523             m_currentDesignDocumentController->loadCurrentModel();
524         }
525
526         QList<RewriterView::Error> errors = m_currentDesignDocumentController->qmlErrors();
527         if (errors.isEmpty()) {
528             // set selection to text cursor
529             RewriterView *rewriter = m_currentDesignDocumentController->rewriterView();
530             const int cursorPos = m_currentTextEdit->textCursor().position();
531             ModelNode node = nodeForPosition(cursorPos);
532             if (node.isValid()) {
533                 rewriter->setSelectedModelNodes(QList<ModelNode>() << node);
534             }
535             enable();
536         } else {
537             disable(errors);
538         }
539
540         connect(m_currentDesignDocumentController.data(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
541                 this, SLOT(updateErrorStatus(QList<RewriterView::Error>)));
542
543     } else {
544         if (m_currentDesignDocumentController->model() && m_currentDesignDocumentController->qmlErrors().isEmpty()) {
545             RewriterView *rewriter = m_currentDesignDocumentController->rewriterView();
546             // visual editor -> text editor
547             ModelNode selectedNode;
548             if (!rewriter->selectedModelNodes().isEmpty())
549                 selectedNode = rewriter->selectedModelNodes().first();
550
551             if (selectedNode.isValid()) {
552                 const int nodeOffset = rewriter->nodeOffset(selectedNode);
553                 if (nodeOffset > 0) {
554                     const ModelNode currentSelectedNode
555                             = nodeForPosition(m_currentTextEdit->textCursor().position());
556                     if (currentSelectedNode != selectedNode) {
557                         int line, column;
558                         m_textEditor->convertPosition(nodeOffset, &line, &column);
559                         m_textEditor->gotoLine(line, column);
560                     }
561                 }
562             }
563         }
564
565         disconnect(m_currentDesignDocumentController.data(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
566                 this, SLOT(updateErrorStatus(QList<RewriterView::Error>)));
567     }
568 }
569
570 void DesignModeWidget::setCurrentDocument(DesignDocumentController *newDesignDocumentController)
571 {
572     if (debug)
573         qDebug() << Q_FUNC_INFO << newDesignDocumentController;
574
575     if (m_currentDesignDocumentController.data() == newDesignDocumentController)
576         return;
577     if (m_currentDesignDocumentController) {
578         setAutoSynchronization(false);
579         saveSettings();
580     }
581
582     if (currentDesignDocumentController()) {
583         disconnect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)),
584             this, SLOT(undoAvailable(bool)));
585         disconnect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)),
586             this, SLOT(redoAvailable(bool)));
587     }
588
589     m_currentDesignDocumentController = newDesignDocumentController;
590
591     if (currentDesignDocumentController()) {
592         connect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)),
593             this, SLOT(undoAvailable(bool)));
594         connect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)),
595             this, SLOT(redoAvailable(bool)));
596     }
597
598     if (m_currentDesignDocumentController) {
599
600         setAutoSynchronization(true);
601         m_undoAction->setEnabled(m_currentDesignDocumentController->isUndoAvailable());
602         m_redoAction->setEnabled(m_currentDesignDocumentController->isRedoAvailable());
603     } else {
604         //detach all views
605         m_undoAction->setEnabled(false);
606         m_redoAction->setEnabled(false);
607     }
608 }
609
610 void DesignModeWidget::setup()
611 {
612     QList<Core::INavigationWidgetFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<Core::INavigationWidgetFactory>();
613
614     QWidget *openDocumentsWidget = 0;
615     QWidget *projectsExplorer = 0;
616     QWidget *fileSystemExplorer = 0;
617
618
619     foreach(Core::INavigationWidgetFactory *factory, factories)
620     {
621         Core::NavigationView navigationView;
622         navigationView.widget = 0;
623         if (factory->id() == QLatin1String("Projects")) {
624             navigationView = factory->createWidget();
625             projectsExplorer = navigationView.widget;
626             projectsExplorer->setWindowTitle(tr("Projects"));
627         } else if (factory->id() == QLatin1String("File System")) {
628             navigationView = factory->createWidget();
629             fileSystemExplorer = navigationView.widget;
630             fileSystemExplorer->setWindowTitle(tr("File System"));
631         } else if (factory->id() == QLatin1String("Open Documents")) {
632             navigationView = factory->createWidget();
633             openDocumentsWidget = navigationView.widget;
634             openDocumentsWidget->setWindowTitle(tr("Open Documents"));
635         }
636
637         if (navigationView.widget)
638         {
639             QFile file(":/qmldesigner/stylesheet.css");
640             file.open(QFile::ReadOnly);
641             QFile file2(":/qmldesigner/scrollbar.css");
642             file2.open(QFile::ReadOnly);
643
644             QString labelStyle = QLatin1String("QLabel { background-color: #4f4f4f; }");
645
646             QString styleSheet = file.readAll() + file2.readAll() + labelStyle;
647             navigationView.widget->setStyleSheet(styleSheet);
648         }
649     }
650
651     m_nodeInstanceView = new NodeInstanceView(this);
652      // Sidebar takes ownership
653     m_navigator = new NavigatorView;
654     m_allPropertiesBox = new AllPropertiesBox;
655     m_itemLibraryView = new ItemLibraryView(this);
656
657     m_statesEditorView = new StatesEditorView(this);
658     
659     m_formEditorView = new FormEditorView(this);
660
661     m_fakeToolBar = Core::EditorManager::createToolBar(this);
662
663     m_mainSplitter = new MiniSplitter(this);
664     m_mainSplitter->setObjectName("mainSplitter");
665
666     // warning frame should be not in layout, but still child of the widget
667     m_warningWidget = new DocumentWarningWidget(this);
668     m_warningWidget->setVisible(false);
669
670     Core::SideBarItem *navigatorItem = new Core::SideBarItem(m_navigator->widget(), QLatin1String(SB_NAVIGATOR));
671     Core::SideBarItem *libraryItem = new ItemLibrarySideBarItem(m_itemLibraryView->widget(), QLatin1String(SB_LIBRARY));
672     Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_allPropertiesBox.data(), QLatin1String(SB_PROPERTIES));
673
674     // default items
675     m_sideBarItems << navigatorItem << libraryItem << propertiesItem;
676
677     if (projectsExplorer) {
678         Core::SideBarItem *projectExplorerItem = new Core::SideBarItem(projectsExplorer, QLatin1String(SB_PROJECTS));
679         m_sideBarItems << projectExplorerItem;
680     }
681
682     if (fileSystemExplorer) {
683         Core::SideBarItem *fileSystemExplorerItem = new Core::SideBarItem(fileSystemExplorer, QLatin1String(SB_FILESYSTEM));
684         m_sideBarItems << fileSystemExplorerItem;
685     }
686
687     if (openDocumentsWidget) {
688         Core::SideBarItem *openDocumentsItem = new Core::SideBarItem(openDocumentsWidget, QLatin1String(SB_OPENDOCUMENTS));
689         m_sideBarItems << openDocumentsItem;
690     }
691
692     m_leftSideBar = new Core::SideBar(m_sideBarItems, QList<Core::SideBarItem*>() << navigatorItem << libraryItem);
693     m_rightSideBar = new Core::SideBar(m_sideBarItems, QList<Core::SideBarItem*>() << propertiesItem);
694
695     connect(m_leftSideBar, SIGNAL(availableItemsChanged()), SLOT(updateAvailableSidebarItemsRight()));
696     connect(m_rightSideBar, SIGNAL(availableItemsChanged()), SLOT(updateAvailableSidebarItemsLeft()));
697
698     connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()),
699             this, SLOT(deleteSidebarWidgets()));
700
701     m_fakeToolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
702     //m_fakeToolBar->addEditor(textEditor()); ### what does this mean?
703     m_fakeToolBar->setNavigationVisible(false);
704
705     connect(m_fakeToolBar, SIGNAL(closeClicked()), this, SLOT(closeCurrentEditor()));
706
707     // right area:
708     QWidget *centerWidget = new QWidget;
709     {
710         QVBoxLayout *rightLayout = new QVBoxLayout(centerWidget);
711         rightLayout->setMargin(0);
712         rightLayout->setSpacing(0);
713         rightLayout->addWidget(m_fakeToolBar);
714         //### we now own these here
715         rightLayout->addWidget(m_statesEditorView->widget());
716
717         FormEditorContext *context = new FormEditorContext(m_formEditorView->widget());
718         Core::ICore::instance()->addContextObject(context);
719
720         // editor and output panes
721         m_outputPlaceholderSplitter->addWidget(m_formEditorView->widget());
722         m_outputPlaceholderSplitter->addWidget(m_outputPanePlaceholder);
723         m_outputPlaceholderSplitter->setStretchFactor(0, 10);
724         m_outputPlaceholderSplitter->setStretchFactor(1, 0);
725         m_outputPlaceholderSplitter->setOrientation(Qt::Vertical);
726
727         rightLayout->addWidget(m_outputPlaceholderSplitter);
728     }
729
730     // m_mainSplitter area:
731     m_mainSplitter->addWidget(m_leftSideBar);
732     m_mainSplitter->addWidget(centerWidget);
733     m_mainSplitter->addWidget(m_rightSideBar);
734
735     // Finishing touches:
736     m_mainSplitter->setStretchFactor(1, 1);
737     m_mainSplitter->setSizes(QList<int>() << 150 << 300 << 150);
738
739     QLayout *mainLayout = new QBoxLayout(QBoxLayout::RightToLeft, this);
740     mainLayout->setMargin(0);
741     mainLayout->setSpacing(0);
742     mainLayout->addWidget(m_mainSplitter);
743
744     m_warningWidget->setVisible(false);
745     m_statesEditorView->widget()->setEnabled(true);
746     m_leftSideBar->setEnabled(true);
747     m_rightSideBar->setEnabled(true);
748     m_leftSideBar->setCloseWhenEmpty(true);
749     m_rightSideBar->setCloseWhenEmpty(true);
750
751     readSettings();
752
753     show();
754     QApplication::processEvents();
755 }
756
757 void DesignModeWidget::updateAvailableSidebarItemsRight()
758 {
759     // event comes from m_leftSidebar, so update right side.
760     m_rightSideBar->setUnavailableItemIds(m_leftSideBar->unavailableItemIds());
761 }
762
763 void DesignModeWidget::updateAvailableSidebarItemsLeft()
764 {
765     // event comes from m_rightSidebar, so update left side.
766     m_leftSideBar->setUnavailableItemIds(m_rightSideBar->unavailableItemIds());
767 }
768
769 void DesignModeWidget::deleteSidebarWidgets()
770 {
771     delete m_leftSideBar;
772     delete m_rightSideBar;
773     m_leftSideBar = 0;
774     m_rightSideBar = 0;
775 }
776
777 void DesignModeWidget::resizeEvent(QResizeEvent *event)
778 {
779     if (m_warningWidget)
780         m_warningWidget->move(QPoint(event->size().width() / 2, event->size().height() / 2));
781     QWidget::resizeEvent(event);
782 }
783
784
785 bool DesignModeWidget::isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const {
786     return (nodeOffset <= cursorPos) && (nodeOffset + nodeLength > cursorPos);
787 }
788
789
790 ModelNode DesignModeWidget::nodeForPosition(int cursorPos) const
791 {
792     RewriterView *rewriter = m_currentDesignDocumentController->rewriterView();
793     QList<ModelNode> nodes = rewriter->allModelNodes();
794
795     ModelNode bestNode;
796     int bestNodeOffset = -1;
797
798     foreach (const ModelNode &node, nodes) {
799         const int nodeOffset = rewriter->nodeOffset(node);
800         const int nodeLength = rewriter->nodeLength(node);
801         if (isInNodeDefinition(nodeOffset, nodeLength, cursorPos)
802             && (nodeOffset > bestNodeOffset)) {
803             bestNode = node;
804             bestNodeOffset = nodeOffset;
805         }
806     }
807
808     return bestNode;
809 }
810
811
812 QString DesignModeWidget::contextHelpId() const
813 {
814     if (m_currentDesignDocumentController)
815         return m_currentDesignDocumentController->contextHelpId();
816     return QString();
817 }
818
819 } // namespace Internal
820 } // namespace Designer