123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "EditorDefs.h"
- #include "WelcomeScreenDialog.h"
- // Qt
- #include <QTableWidget>
- #include <QTableWidgetItem>
- #include <QToolTip>
- #include <QMenu>
- #include <QDesktopServices>
- #include <QFileDialog>
- #include <QMessageBox>
- #include <QScreen>
- #include <QDesktopWidget>
- #include <QTimer>
- #include <QDateTime>
- #include <AzCore/Utils/Utils.h>
- // AzToolsFramework
- #include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
- // AzQtComponents
- #include <AzQtComponents/Components/Widgets/CheckBox.h>
- #include <AzQtComponents/Components/WindowDecorationWrapper.h>
- #include <AzQtComponents/Utilities/PixmapScaleUtilities.h>
- // Editor
- #include "Settings.h"
- #include "MainWindow.h"
- #include "CryEdit.h"
- #include "LevelFileDialog.h"
- AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
- #include <WelcomeScreen/ui_WelcomeScreenDialog.h>
- AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
- using namespace AzQtComponents;
- #define WMSEVENTNAME "WMSEvent"
- #define WMSEVENTOPERATION "operation"
- static int GetSmallestScreenHeight()
- {
- int smallestHeight = -1;
- for (QScreen* screen : QApplication::screens())
- {
- int screenHeight = screen->availableGeometry().height();
- if ((smallestHeight < 0) || (smallestHeight > screenHeight))
- {
- smallestHeight = screenHeight;
- }
- }
- return smallestHeight;
- }
- WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
- : QDialog(new WindowDecorationWrapper(WindowDecorationWrapper::OptionAutoAttach | WindowDecorationWrapper::OptionAutoTitleBarButtons, pParent), Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowTitleHint)
- , ui(new Ui::WelcomeScreenDialog)
- , m_pRecentList(nullptr)
- {
- ui->setupUi(this);
- // Set the project preview image
- QString projectPreviewPath = QDir(AZ::Utils::GetProjectPath().c_str()).filePath("preview.png");
- QFileInfo projectPreviewPathInfo(projectPreviewPath);
- if (!projectPreviewPathInfo.exists() || !projectPreviewPathInfo.isFile())
- {
- projectPreviewPath = ":/WelcomeScreenDialog/DefaultProjectImage.png";
- }
- ui->activeProjectIcon->setPixmap(
- AzQtComponents::ScalePixmapForScreenDpi(
- QPixmap(projectPreviewPath),
- screen(),
- ui->activeProjectIcon->size(),
- Qt::KeepAspectRatioByExpanding,
- Qt::SmoothTransformation
- )
- );
- ui->recentLevelTable->setColumnCount(3);
- ui->recentLevelTable->setMouseTracking(true);
- ui->recentLevelTable->setContextMenuPolicy(Qt::CustomContextMenu);
- ui->recentLevelTable->horizontalHeader()->hide();
- ui->recentLevelTable->verticalHeader()->hide();
- ui->recentLevelTable->setSelectionBehavior(QAbstractItemView::SelectRows);
- ui->recentLevelTable->setSelectionMode(QAbstractItemView::SingleSelection);
- ui->recentLevelTable->setIconSize(QSize(20, 20));
- installEventFilter(this);
- auto projectDisplayName = AZ::Utils::GetProjectDisplayName();
- ui->currentProjectName->setText(projectDisplayName.c_str());
- ui->newLevelButton->setDefault(true);
- // Hide these buttons until the new functionality is added
- ui->gridButton->hide();
- ui->objectListButton->hide();
- ui->switchProjectButton->hide();
- connect(ui->recentLevelTable, &QWidget::customContextMenuRequested, this, &WelcomeScreenDialog::OnShowContextMenu);
- connect(ui->recentLevelTable, &QTableWidget::entered, this, &WelcomeScreenDialog::OnShowToolTip);
- connect(ui->recentLevelTable, &QTableWidget::clicked, this, &WelcomeScreenDialog::OnRecentLevelTableItemClicked);
- connect(ui->newLevelButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnNewLevelBtnClicked);
- connect(ui->levelFileLabel, &QLabel::linkActivated, this, &WelcomeScreenDialog::OnNewLevelLabelClicked);
- connect(ui->openLevelButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnOpenLevelBtnClicked);
- // Adjust the height, if need be
- // Do it in the constructor so that the WindowDecoratorWrapper handles it correctly
- int smallestHeight = GetSmallestScreenHeight();
- if (smallestHeight < geometry().height())
- {
- const int SOME_PADDING_IN_PIXELS = 90;
- int difference = geometry().height() - (smallestHeight - SOME_PADDING_IN_PIXELS);
- QRect newGeometry = geometry().adjusted(0, difference / 2, 0, -difference / 2);
- setMinimumSize(minimumSize().width(), newGeometry.height());
- resize(newGeometry.size());
- }
- m_levelExtension = EditorUtils::LevelFile::GetDefaultFileExtension();
- }
- WelcomeScreenDialog::~WelcomeScreenDialog()
- {
- delete ui;
- }
- void WelcomeScreenDialog::done(int result)
- {
- QDialog::done(result);
- }
- const QString& WelcomeScreenDialog::GetLevelPath()
- {
- return m_levelPath;
- }
- bool WelcomeScreenDialog::eventFilter(QObject *watched, QEvent *event)
- {
- if (event->type() == QEvent::Show)
- {
- ui->recentLevelTable->horizontalHeader()->resizeSection(0, ui->nameLabel->width());
- ui->recentLevelTable->horizontalHeader()->resizeSection(1, ui->modifiedLabel->width());
- ui->recentLevelTable->horizontalHeader()->resizeSection(2, ui->typeLabel->width());
- }
- return QDialog::eventFilter(watched, event);
- }
- bool WelcomeScreenDialog::IsValidLevelName(const QString& path)
- {
- QStringList pathParts = Path::SplitIntoSegments(path);
- QString levelName = pathParts.at(pathParts.size() - 1);
- if (levelName.endsWith(".prefab", Qt::CaseInsensitive))
- {
- // If the level is a prefab, check the container name.
- levelName = pathParts.at(pathParts.size() - 2);
- }
- QRegExpValidator validator(QRegExp("^[a-zA-Z0-9_\\-./]*$"));
- int pos = 0;
- return validator.validate(levelName, pos);
- }
- void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
- {
- if (!pList)
- {
- return;
- }
- m_pRecentList = pList;
- auto projectPath = AZ::Utils::GetProjectPath();
- QString gamePath{projectPath.c_str()};
- Path::ConvertSlashToBackSlash(gamePath);
- gamePath = Path::ToUnixPath(gamePath.toLower());
- gamePath = Path::AddSlash(gamePath);
- QString sCurDir = (Path::GetEditingGameDataFolder() + QDir::separator().toLatin1()).c_str();
- int nCurDir = sCurDir.length();
- int recentListSize = pList->GetSize();
- int currentRow = 0;
- ui->recentLevelTable->setRowCount(recentListSize);
- for (int i = 0; i < recentListSize; ++i)
- {
- const QString& recentFile = pList->m_arrNames[i];
- if (recentFile.endsWith(m_levelExtension) && IsValidLevelName(recentFile))
- {
- if (CFileUtil::Exists(recentFile, false))
- {
- QString sCurEntryDir = recentFile.left(nCurDir);
- if (sCurEntryDir.compare(sCurDir, Qt::CaseInsensitive) == 0)
- {
- QString fullPath = recentFile;
- const QString name = Path::GetFile(fullPath);
- Path::ConvertSlashToBackSlash(fullPath);
- fullPath = Path::ToUnixPath(fullPath.toLower());
- fullPath = Path::AddSlash(fullPath);
- if (fullPath.contains(gamePath))
- {
- if (gSettings.prefabSystem)
- {
- QIcon icon;
- icon.addFile(QString::fromUtf8(":/Level/level.svg"), QSize(), QIcon::Normal, QIcon::Off);
- ui->recentLevelTable->setItem(currentRow, 0, new QTableWidgetItem(icon, name));
- }
- else
- {
- ui->recentLevelTable->setItem(currentRow, 0, new QTableWidgetItem(name));
- }
- QFileInfo file(recentFile);
- QDateTime dateTime = file.lastModified();
- QString date = QLocale::system().toString(dateTime.date(), QLocale::ShortFormat) + " " +
- QLocale::system().toString(dateTime.time(), QLocale::LongFormat);
- ui->recentLevelTable->setItem(currentRow, 1, new QTableWidgetItem(date));
- ui->recentLevelTable->setItem(currentRow++, 2, new QTableWidgetItem(tr("Level")));
- m_levels.push_back(std::make_pair(name, recentFile));
- }
- }
- }
- }
- }
- ui->recentLevelTable->setRowCount(currentRow);
- ui->recentLevelTable->setMinimumHeight(currentRow * ui->recentLevelTable->verticalHeader()->defaultSectionSize());
- ui->recentLevelTable->setMaximumHeight(currentRow * ui->recentLevelTable->verticalHeader()->defaultSectionSize());
- ui->levelFileLabel->setVisible(currentRow ? false : true);
- ui->recentLevelTable->setCurrentIndex(QModelIndex());
- }
- void WelcomeScreenDialog::RemoveLevelEntry(int index)
- {
- TNamePathPair levelPath = m_levels[index];
- ui->recentLevelTable->removeRow(index);
- m_levels.erase(m_levels.begin() + index);
- if (!m_pRecentList)
- {
- return;
- }
- for (int i = 0; i < m_pRecentList->GetSize(); ++i)
- {
- QString fullPath = m_pRecentList->m_arrNames[i];
- QString fullPath2 = levelPath.second;
- // path from recent list
- Path::ConvertSlashToBackSlash(fullPath);
- fullPath = Path::ToUnixPath(fullPath.toLower());
- fullPath = Path::AddPathSlash(fullPath);
- // path from our dashboard list
- Path::ConvertSlashToBackSlash(fullPath2);
- fullPath2 = Path::ToUnixPath(fullPath2.toLower());
- fullPath2 = Path::AddPathSlash(fullPath2);
- if (fullPath == fullPath2)
- {
- m_pRecentList->Remove(index);
- break;
- }
- }
- m_pRecentList->WriteList();
- }
- void WelcomeScreenDialog::OnShowToolTip(const QModelIndex& index)
- {
- const QString& fullPath = m_levels[index.row()].second;
- QToolTip::showText(QCursor::pos(), QString("Open level: %1").arg(fullPath));
- }
- void WelcomeScreenDialog::OnShowContextMenu(const QPoint& pos)
- {
- QModelIndex index = ui->recentLevelTable->indexAt(pos);
- if (index.isValid())
- {
- QString level = ui->recentLevelTable->itemAt(pos)->text();
- QPoint globalPos = ui->recentLevelTable->viewport()->mapToGlobal(pos);
- QMenu contextMenu;
- contextMenu.addAction(QString("Remove " + level + " from recent list"));
- QAction* selectedItem = contextMenu.exec(globalPos);
- if (selectedItem)
- {
- RemoveLevelEntry(index.row());
- }
- }
- }
- void WelcomeScreenDialog::OnNewLevelBtnClicked([[maybe_unused]] bool checked)
- {
- m_levelPath = "new";
- accept();
- }
- void WelcomeScreenDialog::OnNewLevelLabelClicked(const QString& path)
- {
- if (path == "Create")
- {
- OnNewLevelBtnClicked(true);
- }
- else
- {
- OnOpenLevelBtnClicked(true);
- }
- }
- void WelcomeScreenDialog::OnOpenLevelBtnClicked([[maybe_unused]] bool checked)
- {
- CLevelFileDialog dlg(true, this);
- if (dlg.exec() == QDialog::Accepted)
- {
- m_levelPath = dlg.GetFileName();
- accept();
- }
- }
- void WelcomeScreenDialog::OnRecentLevelTableItemClicked(const QModelIndex& modelIndex)
- {
- int index = modelIndex.row();
- if (index >= 0 && index < m_levels.size())
- {
- m_levelPath = m_levels[index].second;
- accept();
- }
- }
- void WelcomeScreenDialog::OnCloseBtnClicked([[maybe_unused]] bool checked)
- {
- accept();
- }
- void WelcomeScreenDialog::previewAreaScrolled()
- {
- //this should only be reported once per session
- if (m_messageScrollReported)
- {
- return;
- }
- m_messageScrollReported = true;
- }
- #include <WelcomeScreen/moc_WelcomeScreenDialog.cpp>
|