/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "stdafx.h" #include "StackEventsWidget.h" #include "IEditor.h" #include <QAction> #include <QApplication> #include <QClipboard> #include <QDebug> #include <QHBoxLayout> #include <QHeaderView> #include <QLabel> #include <QMenu> #include <QMovie> #include <QScrollArea> #include <QTableView> #include <QTextEdit> #include <QTimer> #include <QToolButton> #include <QVBoxLayout> #include <AzQtComponents/Components/StyledBusyLabel.h> #include <DetailWidget/StackEventsWidget.moc> StackEventsWidget::StackEventsWidget(QSharedPointer<IStackEventsModel> stackEventsModel, QWidget* parent) : QFrame{parent} , m_stackEventsModel{stackEventsModel} { setObjectName("StackEvents"); auto mainLayout = new QVBoxLayout {this}; mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); mainLayout->addWidget(CreateTitleBar(), 0); auto content = new QFrame {this}; content->setObjectName("Content"); content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored); mainLayout->addWidget(content, 1); auto contentLayout = new QVBoxLayout {content}; contentLayout->setSpacing(0); contentLayout->setContentsMargins(0, 0, 0, 0); m_logTable = new QTableView {content}; m_logTable->setObjectName("Table"); m_logTable->setModel(m_stackEventsModel.data()); m_logTable->verticalHeader()->hide(); m_logTable->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding); m_logTable->setWordWrap(true); m_logTable->setEditTriggers(QTableView::NoEditTriggers); m_logTable->setSelectionMode(QTableView::SingleSelection); m_logTable->setFocusPolicy(Qt::ClickFocus); m_logTable->setContextMenuPolicy(Qt::CustomContextMenu); QHeaderView* headerView = m_logTable->horizontalHeader(); headerView->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); headerView->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); contentLayout->addWidget(m_logTable, 1); connect(m_stackEventsModel.data(), &IStackEventsModel::rowsInserted, this, &StackEventsWidget::OnRowsInserted); connect(m_logTable->horizontalHeader(), &QHeaderView::sectionResized, m_logTable, &QTableView::resizeRowsToContents); connect(m_logTable, &QTableView::customContextMenuRequested, this, &StackEventsWidget::OnCustomContextMenuRequested); } QWidget* StackEventsWidget::CreateTitleBar() { auto titleBar = new QFrame {}; titleBar->setObjectName("TitleBar"); titleBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); auto titleBarLayout = new QHBoxLayout {}; titleBarLayout->setSizeConstraint(QLayout::SizeConstraint::SetDefaultConstraint); titleBar->setLayout(titleBarLayout); auto titleLabel = new QLabel { tr("Progress log") }; titleLabel->setObjectName("Title"); titleLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); titleBarLayout->addWidget(titleLabel); m_statusInProgress = new QWidget {}; m_statusInProgress->setObjectName("InProgress"); m_statusInProgress->setToolTip(tr( "<span>" "This update may take some time to complete. The duration will depend on the kind " "of updates you are making and the number of resources you are pushing to the cloud. " "You may make additional changes while this update is in progress, but you can only " "push one update the cloud at a time." "</span>")); titleBarLayout->addWidget(m_statusInProgress); auto statusInProgressLayout = new QHBoxLayout {}; statusInProgressLayout->setSizeConstraint(QLayout::SizeConstraint::SetDefaultConstraint); m_statusInProgress->setLayout(statusInProgressLayout); auto statusInProgressLabel = new AzQtComponents::StyledBusyLabel(); statusInProgressLabel->SetIsBusy(true); statusInProgressLabel->SetBusyIconSize(14); statusInProgressLayout->addWidget(statusInProgressLabel); auto statusInProgressText = new QLabel { tr("Operation in progress") }; statusInProgressText->setObjectName("Text"); statusInProgressText->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); statusInProgressLayout->addWidget(statusInProgressText); m_statusSucceeded = new QLabel { tr("Operation succeeded") }; m_statusSucceeded->setObjectName("Succeeded"); m_statusSucceeded->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); titleBarLayout->addWidget(m_statusSucceeded); m_statusFailed = new QLabel { tr("Operation failed") }; m_statusFailed->setObjectName("Failed"); m_statusFailed->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); titleBarLayout->addWidget(m_statusFailed); titleBarLayout->addStretch(); connect(m_stackEventsModel.data(), &IStackEventsModel::CommandStatusChanged, this, &StackEventsWidget::OnCommandStatusChanged); OnCommandStatusChanged(m_stackEventsModel->GetCommandStatus()); return titleBar; } void StackEventsWidget::OnCommandStatusChanged(IStackEventsModel::CommandStatus commandStatus) { m_statusInProgress->setVisible(commandStatus == IStackEventsModel::CommandStatus::CommandInProgress); m_statusSucceeded->setVisible(commandStatus == IStackEventsModel::CommandStatus::CommandSucceeded); m_statusFailed->setVisible(commandStatus == IStackEventsModel::CommandStatus::CommandFailed); } void StackEventsWidget::OnRowsInserted(const QModelIndex& parent, int first, int last) { for (int row = first; row <= last; ++row) { m_logTable->resizeRowToContents(row); } m_logTable->resizeColumnToContents(IStackEventsModel::Columns::StatusColumn); m_logTable->resizeColumnToContents(IStackEventsModel::Columns::TimeColumn); m_logTable->scrollToBottom(); } void StackEventsWidget::OnCustomContextMenuRequested(const QPoint& pos) { QModelIndex index = m_logTable->indexAt(pos); if (index.isValid()) { auto eventContextMenu = new QMenu { this }; auto action = eventContextMenu->addAction(tr("Copy to clipboard")); connect(action, &QAction::triggered, this, [this] { QApplication::clipboard()->setText(m_logTable->currentIndex().data().toString()); }); eventContextMenu->popup(m_logTable->mapToGlobal(pos)); } } void StackEventsWidget::SetStackEventsModel(QSharedPointer<IStackEventsModel> stackEventsModel) { disconnect(m_stackEventsModel.data(), &IStackEventsModel::CommandStatusChanged, this, &StackEventsWidget::OnCommandStatusChanged); disconnect(m_stackEventsModel.data(), &IStackEventsModel::rowsInserted, this, &StackEventsWidget::OnRowsInserted); m_stackEventsModel = stackEventsModel; m_logTable->setModel(stackEventsModel.data()); connect(m_stackEventsModel.data(), &IStackEventsModel::CommandStatusChanged, this, &StackEventsWidget::OnCommandStatusChanged); connect(m_stackEventsModel.data(), &IStackEventsModel::rowsInserted, this, &StackEventsWidget::OnRowsInserted); OnCommandStatusChanged(m_stackEventsModel->GetCommandStatus()); OnRowsInserted(QModelIndex {}, 0, m_stackEventsModel->rowCount() - 1); }