diff options
author | Samuli Piippo <samuli.piippo@qt.io> | 2018-12-05 15:07:18 +0200 |
---|---|---|
committer | Samuli Piippo <samuli.piippo@qt.io> | 2018-12-05 15:07:43 +0200 |
commit | 329a996f6a52494ef677107593a0146c71a2880a (patch) | |
tree | c191128601f69090fe40e730a330d20ac0cf3e3e /src/bench | |
parent | 80d6c28c692c466fbc819ec3b327f3cd24492834 (diff) | |
parent | 8f344fdc478cd18a935adc41f9ef31b1495efad3 (diff) |
Merge remote-tracking branch 'origin/5.11' into 5.12
* origin/5.11:
Add *.qmlc to .gitignore
Fix examples installation path
QmlLive project concept
Update docs for release 5.11
Bench: Use temporary QCoreApplication instance for arguments parsing
Allow to limit the number of watched directories
HostModel: Fix unintended fallthrough
Improve log output with blocking connect
Use user-specific keys for IPC resources
Bench: Fix warning about hidden setModel
Bench: Destroy main window on exit
Bench: Fix About dialog title
Bench: Fix assertion failure on double click in directory preview
Bench: Fix locating previewGenerator on Windows
Change-Id: Ib416b116b4fdf475eb35e7d8fba985b6d6fb9026
Diffstat (limited to 'src/bench')
-rw-r--r-- | src/bench/aboutdialog.cpp | 2 | ||||
-rw-r--r-- | src/bench/bench.pro | 6 | ||||
-rw-r--r-- | src/bench/benchlivenodeengine.cpp | 2 | ||||
-rw-r--r-- | src/bench/hostmanager.h | 2 | ||||
-rw-r--r-- | src/bench/hostmodel.cpp | 10 | ||||
-rw-r--r-- | src/bench/main.cpp | 97 | ||||
-rw-r--r-- | src/bench/mainwindow.cpp | 159 | ||||
-rw-r--r-- | src/bench/mainwindow.h | 14 | ||||
-rw-r--r-- | src/bench/newprojectwizard.cpp | 246 | ||||
-rw-r--r-- | src/bench/newprojectwizard.h | 106 | ||||
-rw-r--r-- | src/bench/options.cpp | 11 | ||||
-rw-r--r-- | src/bench/options.h | 4 | ||||
-rw-r--r-- | src/bench/qmlpreviewadapter.cpp | 2 |
13 files changed, 623 insertions, 38 deletions
diff --git a/src/bench/aboutdialog.cpp b/src/bench/aboutdialog.cpp index c9c37bf..fdae1f7 100644 --- a/src/bench/aboutdialog.cpp +++ b/src/bench/aboutdialog.cpp @@ -41,7 +41,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) { - setWindowTitle(tr("About Qt QML Live")); + setWindowTitle(tr("About Qt QmlLive")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); QVBoxLayout *layout = new QVBoxLayout(this); diff --git a/src/bench/bench.pro b/src/bench/bench.pro index d6a94ae..038da41 100644 --- a/src/bench/bench.pro +++ b/src/bench/bench.pro @@ -27,7 +27,8 @@ SOURCES += \ importpathoptionpage.cpp \ hostdiscoverymanager.cpp \ autodiscoveryhostsdialog.cpp \ - options.cpp + options.cpp \ + newprojectwizard.cpp HEADERS += \ aboutdialog.h \ @@ -48,7 +49,8 @@ HEADERS += \ httpproxyoptionpage.h \ hostdiscoverymanager.h \ autodiscoveryhostsdialog.h \ - options.h + options.h \ + newprojectwizard.h FORMS += \ optionsdialog.ui \ diff --git a/src/bench/benchlivenodeengine.cpp b/src/bench/benchlivenodeengine.cpp index 30dd5b5..b671062 100644 --- a/src/bench/benchlivenodeengine.cpp +++ b/src/bench/benchlivenodeengine.cpp @@ -110,7 +110,7 @@ void BenchLiveNodeEngine::initPlugins() //This needs to be QueuedConnection because Qt5 doesn't like it to destruct it's object while it is in a signalHandler connect(adapter, &DirectoryPreviewAdapter::loadDocument, this, [this](const QString &document) { - m_workspaceView->activateDocument(LiveDocument(document)); + m_workspaceView->activateDocument(LiveDocument::resolve(workspace(), document)); }, Qt::QueuedConnection); } diff --git a/src/bench/hostmanager.h b/src/bench/hostmanager.h index 68f241e..11978c0 100644 --- a/src/bench/hostmanager.h +++ b/src/bench/hostmanager.h @@ -68,6 +68,8 @@ private slots: void addHost(int index); private: + using QListView::setModel; + QPointer<LiveHubEngine> m_engine; HostModel* m_model; diff --git a/src/bench/hostmodel.cpp b/src/bench/hostmodel.cpp index 98c102e..2d9418d 100644 --- a/src/bench/hostmodel.cpp +++ b/src/bench/hostmodel.cpp @@ -84,11 +84,11 @@ QVariant HostModel::headerData(int section, Qt::Orientation orientation, int rol return QVariant(); switch (section) { - case 0: if (role == Qt::DisplayRole) return QVariant(); - case 1: if (role == Qt::DisplayRole) return QString("Name"); - case 2: if (role == Qt::DisplayRole) return QString("Version"); - case 3: if (role == Qt::DisplayRole) return QString("System"); - case 4: if (role == Qt::DisplayRole) return QString("Ip"); + case 0: if (role == Qt::DisplayRole) return QVariant(); break; + case 1: if (role == Qt::DisplayRole) return QString("Name"); break; + case 2: if (role == Qt::DisplayRole) return QString("Version"); break; + case 3: if (role == Qt::DisplayRole) return QString("System"); break; + case 4: if (role == Qt::DisplayRole) return QString("Ip"); break; } return QVariant(); diff --git a/src/bench/main.cpp b/src/bench/main.cpp index 728cf9b..4a2f2ea 100644 --- a/src/bench/main.cpp +++ b/src/bench/main.cpp @@ -36,6 +36,7 @@ #include "hostmanager.h" #include "hostmodel.h" +#include "livehubengine.h" #include "options.h" #include "mainwindow.h" #include "qmllive_version.h" @@ -46,6 +47,7 @@ class Application : public QApplication public: static Application *create(int &argc, char **argv); + ~Application() override; protected: Application(int &argc, char **argv); @@ -53,7 +55,14 @@ protected: QString serverName() const; void setDarkStyle(); - void parseArguments(const QStringList &arguments, Options *options); + static void parseArguments(const QStringList &arguments, Options *options); + static const Options *options() { return s_options; } + +private: + static QString userName(); + +private: + static Options *s_options; }; class MasterApplication : public Application @@ -62,6 +71,7 @@ class MasterApplication : public Application public: MasterApplication(int &argc, char **argv); + ~MasterApplication(); private: void listenForArguments(); @@ -83,16 +93,18 @@ private: void forwardArguments(); }; +Options *Application::s_options = 0; + Application *Application::create(int &argc, char **argv) { setApplicationName("QmlLiveBench"); setOrganizationDomain(QLatin1String(QMLLIVE_ORGANIZATION_DOMAIN)); setOrganizationName(QLatin1String(QMLLIVE_ORGANIZATION_NAME)); - // Workaround: Cannot use QCoreApplication::arguments before app is instantiated - const bool hasNoRemoteOption = argc >= 2 && QString::fromLocal8Bit(argv[1]) == QLatin1String("--noremote"); + // Cannot instantiate the actual application yet + parseArguments(QCoreApplication(argc, argv).arguments(), s_options = new Options); - if (hasNoRemoteOption || isMaster()) + if (isMaster()) return new MasterApplication(argc, argv); else return new SlaveApplication(argc, argv); @@ -107,10 +119,19 @@ Application::Application(int &argc, char **argv) setDarkStyle(); } +Application::~Application() +{ + delete s_options, s_options = 0; +} + bool Application::isMaster() { Q_ASSERT(!applicationName().isEmpty()); Q_ASSERT(!organizationDomain().isEmpty() || !organizationName().isEmpty()); + Q_ASSERT(s_options); + + if (s_options->noRemote()) + return true; static QSharedMemory *lock = 0; static bool retv = false; @@ -118,9 +139,10 @@ bool Application::isMaster() if (lock != 0) return retv; - const QString key = QString::fromLatin1("%1.%2-lock") + const QString key = QString::fromLatin1("%1.%2-%3-lock") .arg(organizationDomain().isEmpty() ? organizationName() : organizationDomain()) - .arg(applicationName()); + .arg(applicationName()) + .arg(userName()); lock = new QSharedMemory(key, qApp); @@ -145,9 +167,10 @@ QString Application::serverName() const Q_ASSERT(!applicationName().isEmpty()); Q_ASSERT(!organizationDomain().isEmpty() || !organizationName().isEmpty()); - return QString::fromLatin1("%1.%2-app") + return QString::fromLatin1("%1.%2-%3-app") .arg(organizationDomain().isEmpty() ? organizationName() : organizationDomain()) - .arg(applicationName()); + .arg(applicationName()) + .arg(userName()); } void Application::setDarkStyle() @@ -199,12 +222,14 @@ void Application::parseArguments(const QStringList &arguments, Options *options) "(implies --remoteonly)", "name"); parser.addOption(probeHostOption); QCommandLineOption noRemoteOption("noremote", "do not try to talk to a running bench, do not listen for remote " - "connections. It MUST BE the VERY FIRST argument on command line."); + "connections."); parser.addOption(noRemoteOption); QCommandLineOption remoteOnlyOption("remoteonly", "talk to a running bench, do nothing if none is running."); parser.addOption(remoteOnlyOption); QCommandLineOption pingOption("ping", "just check if there is a bench running and accepting remote connections."); parser.addOption(pingOption); + QCommandLineOption maxWatchesOption("maxdirwatch", "limit the number of directories to watch for changes", "number", QString::number(options->maximumWatches())); + parser.addOption(maxWatchesOption); parser.process(arguments); @@ -231,6 +256,15 @@ void Application::parseArguments(const QStringList &arguments, Options *options) parser.showHelp(-1); } + if (parser.isSet(maxWatchesOption)) { + bool ok; + int value = parser.value(maxWatchesOption).toInt(&ok); + if (!ok) { + qWarning() << "Invalid argument to --maxdirwatch option"; + parser.showHelp(-1); + } + options->setMaximumWatches(value); + } options->setPluginPath(parser.value(pluginPathOption)); options->setImportPaths(parser.values(importPathOption)); @@ -302,6 +336,22 @@ void Application::parseArguments(const QStringList &arguments, Options *options) } } +QString Application::userName() +{ + QString retv; + +#if defined(Q_OS_UNIX) + retv = QString::fromLocal8Bit(qgetenv("USER")); +#elif defined(Q_OS_WIN) + retv = QString::fromLocal8Bit(qgetenv("USERNAME")); +#endif + + if (retv.isEmpty()) + qWarning("Failed to determine system user name"); + + return retv; +} + /* * class MasterApplication */ @@ -310,31 +360,33 @@ MasterApplication::MasterApplication(int &argc, char **argv) : Application(argc, argv) , m_window(new MainWindow) { - Options options; - parseArguments(arguments(), &options); - - if (options.ping()) { + if (options()->ping()) { QTimer::singleShot(0, [] { QCoreApplication::exit(1); }); return; } - if (options.remoteOnly()) { + if (options()->remoteOnly()) { QTimer::singleShot(0, this, &QCoreApplication::quit); return; } - applyOptions(options); + applyOptions(*options()); - if (options.hasNoninteractiveOptions()) { + if (options()->hasNoninteractiveOptions()) { QTimer::singleShot(0, this, &QCoreApplication::quit); } else { m_window->init(); m_window->show(); - if (!options.noRemote()) + if (!options()->noRemote()) listenForArguments(); } } +MasterApplication::~MasterApplication() +{ + delete m_window; +} + void MasterApplication::listenForArguments() { QLocalServer *server = new QLocalServer(this); @@ -390,6 +442,8 @@ void MasterApplication::listenForArguments() void MasterApplication::applyOptions(const Options &options) { + LiveHubEngine::setMaximumWatches(options.maximumWatches()); + if (!options.workspace().isEmpty()) m_window->setWorkspace(QDir(options.workspace()).absolutePath(), false); @@ -474,18 +528,15 @@ void MasterApplication::applyOptions(const Options &options) SlaveApplication::SlaveApplication(int &argc, char **argv) : Application(argc, argv) { - Options options; - parseArguments(arguments(), &options); - - if (options.ping()) { + if (options()->ping()) { QTimer::singleShot(0, &QCoreApplication::quit); return; } - if (!options.remoteOnly() && !options.hasNoninteractiveOptions()) + if (!options()->remoteOnly() && !options()->hasNoninteractiveOptions()) qInfo() << "Another instance running. Activating..."; - warnAboutIgnoredOptions(options); + warnAboutIgnoredOptions(*options()); forwardArguments(); } diff --git a/src/bench/mainwindow.cpp b/src/bench/mainwindow.cpp index 61924aa..982d962 100644 --- a/src/bench/mainwindow.cpp +++ b/src/bench/mainwindow.cpp @@ -48,7 +48,49 @@ #include "allhostswidget.h" #include "hostdiscoverymanager.h" #include "options.h" +#include "newprojectwizard.h" +#include "projectmanager.h" +class ErrorBar : public QFrame +{ + Q_OBJECT + +public: + ErrorBar(QWidget *parent = nullptr) + : QFrame(parent) + { + setFrameShape(QFrame::StyledPanel); + setAutoFillBackground(true); + QPalette p = palette(); + p.setColor(QPalette::Window, Qt::red); + setPalette(p); + + auto layout = new QHBoxLayout(this); + layout->setContentsMargins(4, 4, 4, 4); + + m_label = new QLabel; + m_label->setWordWrap(true); + layout->addWidget(m_label); + + auto button = new QToolButton; + button->setAutoRaise(true); + button->setIcon(QIcon(":images/refresh.svg")); + connect(button, &QAbstractButton::clicked, this, &ErrorBar::retry); + layout->addWidget(button); + } + + void setError(const QString &errorString) + { + m_label->setText(errorString); + setVisible(!errorString.isEmpty()); + } + +signals: + void retry(); + +private: + QLabel *m_label; +}; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -61,6 +103,8 @@ MainWindow::MainWindow(QWidget *parent) , m_allHosts(new AllHostsWidget(this)) , m_hub(new LiveHubEngine(this)) , m_node(new BenchLiveNodeEngine(this)) + , m_newProjectWizard(new NewProjectWizard(this)) + , m_projectManager(new ProjectManager(this)) { setupContent(); setupMenuBar(); @@ -88,6 +132,7 @@ MainWindow::MainWindow(QWidget *parent) connect(m_allHosts, &AllHostsWidget::refreshAll, m_hostManager, &HostManager::refreshAll); connect(m_hostManager, &HostManager::logWidgetAdded, this, &MainWindow::onLogWidgetAdded); connect(m_hostManager, &HostManager::openHostConfig, this, &MainWindow::openPreferences); + connect(m_newProjectWizard, &NewProjectWizard::accepted, this, &MainWindow::newProject); m_qmlDefaultimportList = m_node->qmlEngine()->importPathList(); } @@ -132,9 +177,42 @@ void MainWindow::setupWorkspaceView() { m_workspaceDock = new QDockWidget("Workspace", this); m_workspaceDock->setObjectName("workspace"); - m_workspaceDock->setWidget(m_workspace); m_workspaceDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); m_workspaceDock->setFeatures(QDockWidget::AllDockWidgetFeatures); + + auto contents = new QWidget; + auto layout = new QVBoxLayout(contents); + layout->setContentsMargins(1, 1, 1, 1); + layout->setSpacing(1); + + auto errorBar = new ErrorBar; + layout->addWidget(errorBar); + + auto updateErrorBar = [this, errorBar]() { + QString error; + switch (m_hub->error()) { + case LiveHubEngine::NoError: + break; + case LiveHubEngine::WatcherMaximumReached: + error = tr("Unable to monitor file changes: The configured limit of %1 directories was exceeded.") + .arg(LiveHubEngine::maximumWatches()); + break; + case LiveHubEngine::WatcherSystemError: + error = tr("Unable to monitor file changes. System limit exceeded?"); + break; + } + errorBar->setError(error); + }; + updateErrorBar(); + connect(m_hub, &LiveHubEngine::errorChanged, errorBar, updateErrorBar); + + connect(errorBar, &ErrorBar::retry, this, [this]() { + m_hub->setWorkspace(m_hub->workspace()); + }); + + layout->addWidget(m_workspace); + + m_workspaceDock->setWidget(contents); addDockWidget(Qt::LeftDockWidgetArea, m_workspaceDock); } @@ -177,10 +255,24 @@ void MainWindow::setupMenuBar() { QMenu *file = menuBar()->addMenu(tr("&File")); #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) - m_openWorkspace = file->addAction(QIcon::fromTheme("folder-open"), tr("&Open Workspace..."), this, SLOT(openWorkspace()), QKeySequence::Open); + m_createProject = file->addAction(QIcon::fromTheme("folder-new"), tr("&New Project"), this, SLOT(newProject()), QKeySequence::New); +#else + m_createProject = file->addAction(QIcon::fromTheme("folder-new"), tr("&New Project"), + this, &MainWindow::newProjectWizard, QKeySequence::New); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) + m_openProject = file->addAction(QIcon::fromTheme("folder-open"), tr("&Open Project..."), this, SLOT(openProject()), QKeySequence::Open); +#else + m_openProject = file->addAction(QIcon::fromTheme("folder-open"), tr("&Open Project..."), + this, &MainWindow::openProject, QKeySequence::Open); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) + m_openWorkspace = file->addAction(QIcon::fromTheme("folder-open"), tr("&Open Workspace..."), this, SLOT(openWorkspace()), QKeySequence("Ctrl+W")); #else m_openWorkspace = file->addAction(QIcon::fromTheme("folder-open"), tr("&Open Workspace..."), - this, &MainWindow::openWorkspace, QKeySequence::Open); + this, &MainWindow::openWorkspace, QKeySequence("Ctrl+W")); #endif m_recentMenu = file->addMenu(QIcon::fromTheme("document-open-recent"), "&Recent"); m_recentMenu->setEnabled(false); @@ -341,6 +433,8 @@ void MainWindow::setupToolBar() m_toolBar = addToolBar("ToolBar"); m_toolBar->setObjectName("toolbar"); m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_toolBar->addAction(m_createProject); + m_toolBar->addAction(m_openProject); m_toolBar->addAction(m_openWorkspace); m_toolBar->addSeparator(); m_toolBar->addAction(m_refresh); @@ -517,3 +611,62 @@ void MainWindow::stayOnTop() } show(); } + +void MainWindow::openProject() +{ + QString filter = tr("QmlLive (*.qmllive);; All files (*.*)"); + QString path = QFileDialog::getOpenFileName(this, "Open Project", filter, filter); + if (path.isEmpty()) { + return; + } + if (m_projectManager->read(path)) + { + QStringList paths; + QSettings s; + int count = s.beginReadArray("imports"); + for (int i=0; i<count; i++) { + s.setArrayIndex(i); + paths.append(s.value("path").toString()); + } + s.endArray(); + paths.append(m_projectManager->imports()); + paths.removeDuplicates(); + + //write Application settings + s.beginWriteArray("imports"); + for (int i = 0; i < paths.count(); i++) { + s.setArrayIndex(i); + s.setValue("path", paths.at(i)); + } + s.endArray(); + + setImportPaths(paths); + setWorkspace(m_projectManager->workspace()); + activateDocument(LiveDocument(m_projectManager->mainDocument())); + } +} + +void MainWindow::newProjectWizard() +{ + if (!m_newProjectWizard) { + m_newProjectWizard = new NewProjectWizard(this); + } else { + m_newProjectWizard->restart(); + } + m_newProjectWizard->show(); +} + +void MainWindow::newProject() +{ + m_projectManager->setImports(m_newProjectWizard->imports()); + m_projectManager->setMainDocument(m_newProjectWizard->mainDocument()); + m_projectManager->setWorkspace(m_newProjectWizard->workspace()); + + m_projectManager->create(m_newProjectWizard->projectName()); + + setImportPaths(m_newProjectWizard->imports()); + setWorkspace(m_newProjectWizard->workspace()); + activateDocument(LiveDocument(m_newProjectWizard->mainDocument())); +} + +#include "mainwindow.moc" diff --git a/src/bench/mainwindow.h b/src/bench/mainwindow.h index 4a7e8f1..c3725a2 100644 --- a/src/bench/mainwindow.h +++ b/src/bench/mainwindow.h @@ -50,13 +50,16 @@ class AllHostsWidget; class Host; class HostDiscoveryManager; class Options; +class NewProjectWizard; +class ProjectManager; + QT_FORWARD_DECLARE_CLASS(QToolBar); class MainWindow : public QMainWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); void activateDocument(const LiveDocument &path); void setWorkspace(const QString& path, bool activateRootPath = true); @@ -88,10 +91,13 @@ private slots: void openWorkspace(); void logQuitEvent(); void updateWindowTitle(); - void openPreferences(Host *host = 0); + void openPreferences(Host *host = nullptr); void openRecentFolder(); void clearRecentFolder(); void stayOnTop(); + void openProject(); + void newProjectWizard(); + void newProject(); void onActiveWindowChanged(QQuickWindow *activeWindow); @@ -126,4 +132,8 @@ private: QAction *m_clipRootObject; QToolBar* m_toolBar; QStringList m_qmlDefaultimportList; + QAction *m_openProject; + QAction *m_createProject; + NewProjectWizard *m_newProjectWizard; + ProjectManager *m_projectManager; }; diff --git a/src/bench/newprojectwizard.cpp b/src/bench/newprojectwizard.cpp new file mode 100644 index 0000000..f2fcbbc --- /dev/null +++ b/src/bench/newprojectwizard.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QmlLive tool. +** +** $QT_BEGIN_LICENSE:GPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: GPL-3.0 +** +****************************************************************************/ + +#include "newprojectwizard.h" + +#include <QGridLayout> +#include <QListWidget> +#include <QPushButton> +#include <QFileDialog> +#include "livedocument.h" + +NewProjectWizard::NewProjectWizard(QWidget *parent) + : QWizard(parent) + , m_importListWidget(nullptr) + , m_projectPage(new ProjectPage()) + , m_workspacePage(new WorkspacePage()) + , m_mainDocumentPage(new MainDocumentPage()) +{ + setWizardStyle(QWizard::ClassicStyle); + setOptions(QWizard::NoBackButtonOnStartPage); + addPage(m_projectPage); + addPage(m_workspacePage); + addPage(createImportsPage()); + addPage(m_mainDocumentPage); +} + +MainDocumentPage::MainDocumentPage(QWidget *parent) + : QWizardPage (parent) +{ + setTitle("Main Document"); + QGridLayout *layout = new QGridLayout; + + QLabel *label = new QLabel("Main document: "); + layout->addWidget(label, 0, 0); + + m_mainDocumentField = new QLineEdit; + registerField("mainDocument*", m_mainDocumentField); + layout->addWidget(m_mainDocumentField, 0, 1); + + layout->setColumnStretch(1, 1); + layout->setRowStretch(1, 1); + setLayout(layout); + +} + +QString MainDocumentPage::mainDocument() const +{ + if (m_mainDocumentField) { + return m_mainDocumentField->text(); + } + return ""; +} + +WorkspacePage::WorkspacePage(QWidget *parent) + : QWizardPage (parent) +{ + setTitle("Select Workspace"); + QGridLayout *layout = new QGridLayout; + + QLabel *label = new QLabel("Workspace: "); + layout->addWidget(label, 0, 0); + + m_workspaceField = new QLineEdit; + registerField("workspace*", m_workspaceField); + layout->addWidget(m_workspaceField, 0, 1); + + QPushButton *button = new QPushButton("Select"); + layout->addWidget(button, 0, 2); + connect(button, SIGNAL(clicked()), this, SLOT(selectWorkspacePath())); + + m_warningLabel = new QLabel; + layout->addWidget(m_warningLabel, 1, 0, 1, 3, Qt::AlignTop); + + layout->setColumnStretch(1, 1); + layout->setRowStretch(1, 1); + setLayout(layout); +} + +QString WorkspacePage::workspace() const +{ + if (m_workspaceField) { + return m_workspaceField->text(); + } + return ""; +} + +void WorkspacePage::selectWorkspacePath() +{ + m_warningLabel->setText(""); + QString workspace = QFileDialog::getExistingDirectory(this, "Select Workspace"); + if (!workspace.isEmpty() && m_workspaceField) { + m_workspaceField->setText(workspace); + } +} + +bool WorkspacePage::validatePage() +{ + if (QDir(workspace()).exists()) { + m_warningLabel->setText(""); + return true; + } else { + m_warningLabel->setText("The path you entered does not exist."); + return false; + } +} + +QWizardPage *NewProjectWizard::createImportsPage() +{ + QWizardPage *page = new QWizardPage; + page->setTitle("Imports"); + QGridLayout *layout = new QGridLayout; + + m_importListWidget = new QListWidget; + layout->addWidget(m_importListWidget, 0, 0, 4, 1); + + QPushButton *add = new QPushButton("Add"); + connect(add, SIGNAL(clicked()), this, SLOT(addImportPath())); + layout->addWidget(add, 0, 1); + + QPushButton *edit = new QPushButton("Edit"); + connect(edit, SIGNAL(clicked()), this, SLOT(editImportPath())); + layout->addWidget(edit, 1, 1); + + QPushButton *remove = new QPushButton("Remove"); + connect(remove, SIGNAL(clicked()), this, SLOT(removeImportPath())); + layout->addWidget(remove, 2, 1); + + layout->setRowStretch(4, 1); + page->setLayout(layout); + return page; +} + +ProjectPage::ProjectPage(QWidget *parent) + : QWizardPage (parent) +{ + setTitle("Project Name"); + setSubTitle("This wizard generates a Qt QmlLive project. The QmlLive project file shall describe the" + "common options for a QmlLive project by specifying the workspace folder, the main document" + "and the import paths relative to the project document location."); + + QGridLayout *layout = new QGridLayout; + + QLabel *label = new QLabel("Project name: "); + layout->addWidget(label, 0, 0); + + m_projectField = new QLineEdit; + registerField("projectName*", m_projectField); + m_projectField->setPlaceholderText("MyQmlLiveProject"); + layout->addWidget(m_projectField, 0, 1); + + layout->setColumnStretch(1, 1); + layout->setRowStretch(1, 1); + setLayout(layout); +} + +QString ProjectPage::projectName() const +{ + if (m_projectField) { + return m_projectField->text(); + } + return ""; +} + +QString NewProjectWizard::mainDocument() const +{ + return m_mainDocumentPage->mainDocument(); +} + +QString NewProjectWizard::workspace() const +{ + return m_workspacePage->workspace(); +} + +QStringList NewProjectWizard::imports() const +{ + QStringList list; + if (m_importListWidget) { + for (int i = 0; i < m_importListWidget->count(); i++) { + list.append(m_importListWidget->takeItem(i)->text()); + } + } + + return list; +} + +QString NewProjectWizard::projectName() const +{ + return m_projectPage->projectName(); +} + +void NewProjectWizard::addImportPath() +{ + QString path = QFileDialog::getExistingDirectory(this, "Add Import Path"); + if (path.isEmpty()) { + return; + } + QListWidgetItem *item = new QListWidgetItem(path); + item->setFlags(item->flags () | Qt::ItemIsEditable); + m_importListWidget->addItem(item); + +} + +void NewProjectWizard::editImportPath() +{ + QListWidgetItem *item = m_importListWidget->currentItem(); + if (item) { + m_importListWidget->editItem(item); + } + +} + +void NewProjectWizard::removeImportPath() +{ + QListWidgetItem *item = m_importListWidget->currentItem(); + if (item) { + delete item; + } +} diff --git a/src/bench/newprojectwizard.h b/src/bench/newprojectwizard.h new file mode 100644 index 0000000..b2f5fd6 --- /dev/null +++ b/src/bench/newprojectwizard.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QmlLive tool. +** +** $QT_BEGIN_LICENSE:GPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: GPL-3.0 +** +****************************************************************************/ + +#pragma once + +#include <QWizard> +#include <QWizardPage> +#include <QLineEdit> +#include <QListWidget> +#include <QLabel> + +class ProjectPage : public QWizardPage +{ + Q_OBJECT + +public: + ProjectPage(QWidget *parent = nullptr); + QString projectName() const; + +private: + QLineEdit *m_projectField; +}; + +class WorkspacePage : public QWizardPage +{ + Q_OBJECT + +public: + WorkspacePage(QWidget *parent = nullptr); + QString workspace() const; + bool validatePage() override; + +private slots: + void selectWorkspacePath(); + +private: + QLineEdit *m_workspaceField; + QLabel *m_warningLabel; +}; + +class MainDocumentPage : public QWizardPage +{ + Q_OBJECT + +public: + MainDocumentPage(QWidget *parent = nullptr); + QString mainDocument() const; + +private: + QLineEdit *m_mainDocumentField; +}; + +class NewProjectWizard : public QWizard +{ + Q_OBJECT +public: + explicit NewProjectWizard(QWidget *parent = 0); + QWizardPage* createMainDocumentPage(); + QWizardPage* createWorkspacePage(); + QWizardPage* createImportsPage(); + QWizardPage* createProjectPage(); + + QString mainDocument() const; + QString workspace() const; + QStringList imports() const; + QString projectName() const; + +private slots: + void addImportPath(); + void editImportPath(); + void removeImportPath(); + +private: + QListWidget *m_importListWidget; + ProjectPage *m_projectPage; + WorkspacePage *m_workspacePage; + MainDocumentPage *m_mainDocumentPage; +}; diff --git a/src/bench/options.cpp b/src/bench/options.cpp index 5baedc2..1e1f28b 100644 --- a/src/bench/options.cpp +++ b/src/bench/options.cpp @@ -37,6 +37,7 @@ Options::Options(QObject *parent) , m_remoteOnly(false) , m_ping(false) , m_stayOnTop(false) + , m_maximumWatches(100) { } @@ -174,3 +175,13 @@ void Options::setHostsToProbe(const QStringList &hostNames) { m_hostsToProbe = hostNames; } + +int Options::maximumWatches() const +{ + return m_maximumWatches; +} + +void Options::setMaximumWatches(int maximumWatches) +{ + m_maximumWatches = maximumWatches; +} diff --git a/src/bench/options.h b/src/bench/options.h index e7c84bd..a0ab44f 100644 --- a/src/bench/options.h +++ b/src/bench/options.h @@ -86,6 +86,9 @@ public: QStringList hostsToProbe() const; void setHostsToProbe(const QStringList &hostNames); + int maximumWatches() const; + void setMaximumWatches(int maximumWatches); + private: bool m_noRemote; bool m_remoteOnly; @@ -98,5 +101,6 @@ private: QList<HostOptions> m_hostsToAdd; QStringList m_hostsToRemove; QStringList m_hostsToProbe; + int m_maximumWatches; }; diff --git a/src/bench/qmlpreviewadapter.cpp b/src/bench/qmlpreviewadapter.cpp index ac5415e..21a9623 100644 --- a/src/bench/qmlpreviewadapter.cpp +++ b/src/bench/qmlpreviewadapter.cpp @@ -62,7 +62,7 @@ QImage QmlPreviewAdapter::preview(const QString &path, const QSize &requestedSiz } static const QString program = QCoreApplication::applicationDirPath() + -#ifdef Q_OS_WINDOWS +#ifdef Q_OS_WIN QStringLiteral("/previewGenerator.exe"); #else QStringLiteral("/../libexec/qmllive/previewGenerator"); |