OSDN Git Service

doc: Fixed URL in GettingStartedWelcomePageWidget
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qt4projectmanager / gettingstartedwelcomepagewidget.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** Commercial Usage
10 **
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
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 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
27 **
28 **************************************************************************/
29
30 #include "gettingstartedwelcomepagewidget.h"
31 #include "ui_gettingstartedwelcomepagewidget.h"
32
33 #include <coreplugin/icore.h>
34 #include <coreplugin/helpmanager.h>
35 #include <coreplugin/coreconstants.h>
36 #include <coreplugin/mainwindow.h>
37 #include <projectexplorer/projectexplorer.h>
38
39 #include <utils/pathchooser.h>
40
41 #include <extensionsystem/pluginmanager.h>
42
43 #include <QtCore/QDateTime>
44 #include <QtCore/QDir>
45 #include <QtCore/QFileInfo>
46 #include <QtCore/QDebug>
47 #include <QtCore/QStringBuilder>
48 #include <QtCore/QUrl>
49 #include <QtCore/QTimer>
50 #include <QtCore/QSettings>
51 #include <QtCore/QXmlStreamReader>
52 #include <QtGui/QDialogButtonBox>
53 #include <QtGui/QFont>
54 #include <QtGui/QMessageBox>
55 #include <QtGui/QPushButton>
56 #include <QtGui/QMenu>
57
58 namespace Qt4ProjectManager {
59 namespace Internal {
60
61 const char ExamplePathPropertyName[] = "__qt_ExamplePath";
62 const char HelpPathPropertyName[] = "__qt_HelpPath";
63
64 GettingStartedWelcomePageWidget::GettingStartedWelcomePageWidget(QWidget *parent) :
65     QWidget(parent),
66     ui(new Ui::GettingStartedWelcomePageWidget)
67 {
68     ui->setupUi(this);
69
70     ui->didYouKnowTextBrowser->viewport()->setAutoFillBackground(false);
71
72     connect(ui->tutorialTreeWidget, SIGNAL(activated(QString)), SLOT(slotOpenHelpPage(const QString&)));
73
74     ui->tutorialTreeWidget->addItem(tr("The Qt Creator User Interface"),
75                                         QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-quick-tour.html"));
76     ui->tutorialTreeWidget->addItem(tr("Building and Running an Example"),
77                                         QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-build-example-application.html?view=split"));
78     ui->tutorialTreeWidget->addItem(tr("Creating a Qt C++ Application"),
79                                         QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-writing-program.html?view=split"));
80     ui->tutorialTreeWidget->addItem(tr("Creating a Mobile Application"),
81                                         QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-mobile-example.html?view=split"));
82     ui->tutorialTreeWidget->addItem(tr("Creating a Qt Quick Application"),
83                                         QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-qml-application.html?view=split"));
84
85     srand(QDateTime::currentDateTime().toTime_t());
86     QStringList tips = tipsOfTheDay();
87     m_currentTip = rand()%tips.count();
88
89     QTextDocument *doc = ui->didYouKnowTextBrowser->document();
90     doc->setDefaultStyleSheet("a:link {color:black;}");
91     ui->didYouKnowTextBrowser->setDocument(doc);
92     ui->didYouKnowTextBrowser->setText(tips.at(m_currentTip));
93
94     connect(ui->nextTipBtn, SIGNAL(clicked()), this, SLOT(slotNextTip()));
95     connect(ui->prevTipBtn, SIGNAL(clicked()), this, SLOT(slotPrevTip()));
96     connect(ui->openProjectButton, SIGNAL(clicked()),
97             ProjectExplorer::ProjectExplorerPlugin::instance(),
98             SLOT(openOpenProjectDialog()));
99     connect(ui->createNewProjectButton, SIGNAL(clicked()), this, SLOT(slotCreateNewProject()));
100
101     ui->createNewProjectButton->setIcon(
102             QIcon::fromTheme(QLatin1String("document-new"), ui->createNewProjectButton->icon()));
103     ui->openProjectButton->setIcon(
104             QIcon::fromTheme(QLatin1String("document-open"), ui->openProjectButton->icon()));
105     QTimer::singleShot(0, this, SLOT(slotSetPrivateQmlExamples()));
106 }
107
108 GettingStartedWelcomePageWidget::~GettingStartedWelcomePageWidget()
109 {
110     delete ui;
111 }
112
113 void GettingStartedWelcomePageWidget::slotSetPrivateQmlExamples()
114 {
115     if (!ui->qmlExamplesButton->menu()) {
116         const QString resPath = Core::ICore::instance()->resourcePath();
117         updateQmlExamples(resPath, resPath);
118     }
119  }
120
121 void GettingStartedWelcomePageWidget::updateCppExamples(const QString &examplePath,
122                                                         const QString &sourcePath,
123                                                         const QString &demoXml)
124 {
125
126     QFile description(demoXml);
127     if (!description.open(QFile::ReadOnly))
128         return;
129
130     ui->cppExamplesButton->setEnabled(true);;
131     ui->cppExamplesButton->setText(tr("Choose an example..."));
132
133     QMenu *menu = new QMenu(ui->cppExamplesButton);
134     ui->cppExamplesButton->setMenu(menu);
135
136     QMenu *subMenu = 0;
137     bool inExamples = false;
138     QString dirName;
139     QXmlStreamReader reader(&description);
140
141     while (!reader.atEnd()) {
142         switch (reader.readNext()) {
143             case QXmlStreamReader::StartElement:
144             if (reader.name() == QLatin1String("category")) {
145                 QString name = reader.attributes().value(QLatin1String("name")).toString();
146                 if (name.contains(QLatin1String("tutorial")))
147                     break;
148                 dirName = reader.attributes().value(QLatin1String("dirname")).toString();
149                 subMenu = menu->addMenu(name);
150                 inExamples = true;
151             }
152             if (inExamples && reader.name() == QLatin1String("example")) {
153                 const QChar slash = QLatin1Char('/');
154                 const QString name = reader.attributes().value(QLatin1String("name")).toString();
155                 const QString fn = reader.attributes().value(QLatin1String("filename")).toString();
156                 const QString relativeProPath = slash + dirName + slash + fn + slash + fn + QLatin1String(".pro");
157                 QString fileName = examplePath + relativeProPath;
158                 if (!QFile::exists(fileName))
159                     fileName = sourcePath + QLatin1String("/examples") + relativeProPath;
160                 QString dirName1 = dirName;
161                 dirName1.replace(slash, QLatin1Char('-'));
162                 QString helpPath = QLatin1String("qthelp://com.trolltech.qt/qdoc/") +
163                                    dirName1 +
164                                    QLatin1Char('-') + fn + QLatin1String(".html");
165
166                 QAction *exampleAction = subMenu->addAction(name);
167                 connect(exampleAction, SIGNAL(triggered()), SLOT(slotOpenExample()));
168
169                 exampleAction->setProperty(ExamplePathPropertyName, fileName);
170                 exampleAction->setProperty(HelpPathPropertyName, helpPath);
171             }
172             break;
173             case QXmlStreamReader::EndElement:
174             if (reader.name() == QLatin1String("category"))
175                 inExamples = false;
176             break;
177             default:
178             break;
179         }
180     }
181 }
182
183 void GettingStartedWelcomePageWidget::updateQmlExamples(const QString &examplePath,
184                                                         const QString &sourcePath)
185 {
186     ui->qmlExamplesButton->setText(tr("Choose an example..."));
187
188     QStringList roots;
189     roots << (examplePath + QLatin1String("/declarative"))
190             << (sourcePath + QLatin1String("/examples/declarative"));
191     QMap<QString, QString> exampleProjects;
192
193     foreach (const QString &root, roots) {
194         QList<QFileInfo> examples = QDir(root).entryInfoList(QStringList(), QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name);
195         foreach(const QFileInfo &example, examples) {
196             const QString fileName = example.fileName();
197             if (exampleProjects.contains(fileName))
198                 continue;
199             const QString exampleProject = example.absoluteFilePath()
200                                            + QLatin1Char('/') + fileName
201                                            + QLatin1String(".qmlproject");
202             if (!QFile::exists(exampleProject))
203                 continue;
204             exampleProjects.insert(fileName, exampleProject);
205         }
206     }
207
208     if (!exampleProjects.isEmpty()) {
209         QMenu *menu = new QMenu(ui->qmlExamplesButton);
210         ui->qmlExamplesButton->setMenu(menu);
211
212         QMapIterator<QString, QString> it(exampleProjects);
213         while (it.hasNext()) {
214             it.next();
215             QAction *exampleAction = menu->addAction(it.key());
216             connect(exampleAction, SIGNAL(triggered()), SLOT(slotOpenExample()));
217             exampleAction->setProperty(ExamplePathPropertyName, it.value());
218             // FIXME once we have help for QML examples
219             // exampleAction->setProperty(HelpPathPropertyName, helpPath);
220         }
221     }
222
223     ui->qmlExamplesButton->setEnabled(!exampleProjects.isEmpty());
224 }
225
226 void GettingStartedWelcomePageWidget::updateExamples(const QString &examplePath,
227                                                      const QString &demosPath,
228                                                      const QString &sourcePath)
229 {
230     QString demoxml = demosPath + "/qtdemo/xml/examples.xml";
231     if (!QFile::exists(demoxml)) {
232         demoxml = sourcePath + "/demos/qtdemo/xml/examples.xml";
233         if (!QFile::exists(demoxml))
234             return;
235     }
236     updateCppExamples(examplePath, sourcePath, demoxml);
237     updateQmlExamples(examplePath, sourcePath);
238 }
239
240
241 namespace {
242 void copyRecursive(const QDir& from, const QDir& to, const QString& dir)
243 {
244     QDir dest(to);
245     dest.mkdir(dir);
246     dest.cd(dir);
247     QDir src(from);
248     src.cd(dir);
249     foreach(const QFileInfo& roFile, src.entryInfoList(QDir::Files)) {
250         QFile::copy(roFile.absoluteFilePath(), dest.absolutePath() + '/' + roFile.fileName());
251     }
252     foreach(const QString& roDir, src.entryList(QDir::NoDotAndDotDot|QDir::Dirs)) {
253         copyRecursive(src, dest, QDir(roDir).dirName());
254     }
255 }
256 } // namespace
257
258 void GettingStartedWelcomePageWidget::slotOpenExample()
259 {
260     QAction *action = qobject_cast<QAction*>(sender());
261     if (!action)
262         return;
263
264     QString helpFile = action->property(HelpPathPropertyName).toString();
265     QString proFile = action->property(ExamplePathPropertyName).toString();
266     QStringList files;
267
268     QFileInfo proFileInfo(proFile);
269     // If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail
270     if (!proFileInfo.isWritable())
271     {
272         QDialog d;
273         QGridLayout *lay = new QGridLayout(&d);
274         QLabel *descrLbl = new QLabel;
275         d.setWindowTitle(tr("Copy Project to writable Location?"));
276         descrLbl->setTextFormat(Qt::RichText);
277         descrLbl->setWordWrap(true);
278         descrLbl->setText(tr("<p>The project you are about to open is located in the "
279                              "write-protected location:</p><blockquote>%1</blockquote>"
280                              "<p>Please select a writable location below and click \"Copy Project and Open\" "
281                              "to open a modifiable copy of the project or click \"Keep Project and Open\" "
282                              "to open the project in location.</p><p><b>Note:</b> You will not "
283                              "be able to alter or compile your project in the current location.</p>")
284                           .arg(QDir::toNativeSeparators(proFileInfo.dir().absolutePath())));
285         lay->addWidget(descrLbl, 0, 0, 1, 2);
286         QLabel *txt = new QLabel(tr("&Location:"));
287         Utils::PathChooser *chooser = new Utils::PathChooser;
288         txt->setBuddy(chooser);
289         chooser->setExpectedKind(Utils::PathChooser::Directory);
290         QSettings *settings = Core::ICore::instance()->settings();
291         chooser->setPath(settings->value(
292                 QString::fromLatin1("General/ProjectsFallbackRoot"), QDir::homePath()).toString());
293         lay->addWidget(txt, 1, 0);
294         lay->addWidget(chooser, 1, 1);
295         QDialogButtonBox *bb = new QDialogButtonBox;
296         connect(bb, SIGNAL(accepted()), &d, SLOT(accept()));
297         connect(bb, SIGNAL(rejected()), &d, SLOT(reject()));
298         QPushButton *copyBtn = bb->addButton(tr("&Copy Project and Open"), QDialogButtonBox::AcceptRole);
299         copyBtn->setDefault(true);
300         bb->addButton(tr("&Keep Project and Open"), QDialogButtonBox::RejectRole);
301         lay->addWidget(bb, 2, 0, 1, 2);
302         connect(chooser, SIGNAL(validChanged(bool)), copyBtn, SLOT(setEnabled(bool)));
303         if (d.exec() == QDialog::Accepted) {
304             QString exampleDirName = proFileInfo.dir().dirName();
305             QString toDir = chooser->path();
306             settings->setValue(QString::fromLatin1("General/ProjectsFallbackRoot"), toDir);
307             QDir toDirWithExamplesDir(toDir);
308             if (toDirWithExamplesDir.cd(exampleDirName)) {
309                 toDirWithExamplesDir.cdUp(); // step out, just to not be in the way
310                 QMessageBox::warning(topLevelWidget(), tr("Warning"),
311                                      tr("The specified location already exists. "
312                                         "Please specify a valid location."),
313                                      QMessageBox::Ok, QMessageBox::NoButton);
314                 return;
315             } else {
316                 QDir from = proFileInfo.dir();
317                 from.cdUp();
318                 copyRecursive(from, toDir, exampleDirName);
319                 // set vars to new location
320                 proFileInfo = QFileInfo(toDir + '/'+ exampleDirName + '/' + proFileInfo.fileName());
321                 proFile = proFileInfo.absoluteFilePath();
322             }
323         }
324     }
325
326
327     QString tryFile = proFileInfo.path() + "/main.cpp";
328     files << proFile;
329     if(!QFile::exists(tryFile))
330         tryFile = proFileInfo.path() + '/' + proFileInfo.baseName() + ".cpp";
331     // maybe it's a QML project?
332     if(!QFile::exists(tryFile))
333         tryFile = proFileInfo.path() + '/' + "/main.qml";
334     if(!QFile::exists(tryFile))
335         tryFile = proFileInfo.path() + '/' + proFileInfo.baseName() + ".qml";
336     if(QFile::exists(tryFile))
337         files << tryFile;
338     Core::ICore::instance()->openFiles(files);
339     if (!helpFile.isEmpty())
340         slotOpenContextHelpPage(helpFile);
341 }
342
343 void GettingStartedWelcomePageWidget::slotOpenHelpPage(const QString& url)
344 {
345     Core::HelpManager *helpManager = Core::HelpManager::instance();
346     Q_ASSERT(helpManager);
347     helpManager->handleHelpRequest(url);
348 }
349 void GettingStartedWelcomePageWidget::slotOpenContextHelpPage(const QString& url)
350 {
351     Core::HelpManager *helpManager = Core::HelpManager::instance();
352     Q_ASSERT(helpManager);
353     helpManager->handleHelpRequest(url % QLatin1String("?view=split"));
354 }
355
356 void GettingStartedWelcomePageWidget::slotCreateNewProject()
357 {
358     Core::ICore::instance()->showNewItemDialog(tr("New Project"),
359                                                Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard));
360 }
361
362 void GettingStartedWelcomePageWidget::slotNextTip()
363 {
364     QStringList tips = tipsOfTheDay();
365     m_currentTip = ((m_currentTip+1)%tips.count());
366     ui->didYouKnowTextBrowser->setText(tips.at(m_currentTip));
367 }
368
369 void GettingStartedWelcomePageWidget::slotPrevTip()
370 {
371     QStringList tips = tipsOfTheDay();
372     m_currentTip = ((m_currentTip-1)+tips.count())%tips.count();
373     ui->didYouKnowTextBrowser->setText(tips.at(m_currentTip));
374 }
375
376 QStringList GettingStartedWelcomePageWidget::tipsOfTheDay()
377 {
378     static QStringList tips;
379     if (tips.isEmpty()) {
380         QString altShortcut =
381 #ifdef Q_WS_MAC
382             tr("Cmd", "Shortcut key");
383 #else
384             tr("Alt", "Shortcut key");
385 #endif
386
387         QString ctrlShortcut =
388 #ifdef Q_WS_MAC
389             tr("Cmd", "Shortcut key");
390 #else
391             tr("Ctrl", "Shortcut key");
392 #endif
393
394         //:%1 gets replaced by Alt (Win/Unix) or Cmd (Mac)
395         tips.append(tr("You can show and hide the side bar using <tt>%1+0<tt>.").arg(altShortcut));
396         tips.append(tr("You can fine tune the <tt>Find</tt> function by selecting &quot;Whole Words&quot; "
397                        "or &quot;Case Sensitive&quot;. Simply click on the icons on the right end of the line edit."));
398         tips.append(tr("If you add external libraries to your project, Qt Creator will automatically offer syntax highlighting "
399                         "and code completion."));
400         tips.append(tr("The code completion is CamelCase-aware. For example, to complete <tt>namespaceUri</tt> "
401                        "you can just type <tt>nU</tt> and hit <tt>Ctrl+Space</tt>."));
402         tips.append(tr("You can force code completion at any time using <tt>Ctrl+Space</tt>."));
403         tips.append(tr("You can start Qt Creator with a session by calling <tt>qtcreator &lt;sessionname&gt;</tt>."));
404         tips.append(tr("You can return to edit mode from any other mode at any time by hitting <tt>Escape</tt>."));
405         //:%1 gets replaced by Alt (Win/Unix) or Cmd (Mac)
406         tips.append(tr("You can switch between the output pane by hitting <tt>%1+n</tt> where n is the number denoted "
407                        "on the buttons at the window bottom:"
408                        "<ul><li>1 - Build Issues</li><li>2 - Search Results</li><li>3 - Application Output</li>"
409                        "<li>4 - Compile Output</li></ul>").arg(altShortcut));
410         tips.append(tr("You can quickly search methods, classes, help and more using the "
411                        "<a href=\"qthelp://com.nokia.qtcreator/doc/creator-editor-locator.html\">Locator bar</a> (<tt>%1+K</tt>).").arg(ctrlShortcut));
412         tips.append(tr("You can add custom build steps in the "
413                        "<a href=\"qthelp://com.nokia.qtcreator/doc/creator-build-settings.html\">build settings</a>."));
414         tips.append(tr("Within a session, you can add "
415                        "<a href=\"qthelp://com.nokia.qtcreator/doc/creator-build-dependencies.html\">dependencies</a> between projects."));
416         tips.append(tr("You can set the preferred editor encoding for every project in <tt>Projects -> Editor Settings -> Default Encoding</tt>."));
417         tips.append(tr("You can use Qt Creator with a number of <a href=\"qthelp://com.nokia.qtcreator/doc/creator-version-control.html\">"
418                        "revision control systems</a> such as Subversion, Perforce, CVS and Git."));
419         tips.append(tr("In the editor, <tt>F2</tt> follows symbol definition, <tt>Shift+F2</tt> toggles declaration and definition "
420                        "while <tt>F4</tt> toggles header file and source file."));
421     }
422     return tips;
423 }
424
425
426 } // namespace Internal
427 } // namespace Qt4ProjectManager