File indexing completed on 2024-05-12 05:50:08
0001 /* 0002 SPDX-FileCopyrightText: 2022 Jiří Wolker <woljiri@gmail.com> 0003 SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "welcomeview.h" 0009 0010 #include "mainwindow.h" 0011 #include "recentfilesmodel.h" 0012 0013 #include <KAboutData> 0014 #include <KConfigGroup> 0015 #include <KIO/OpenFileManagerWindowJob> 0016 #include <KIconLoader> 0017 #include <KRecentFilesMenu> 0018 #include <KSharedConfig> 0019 0020 #include <QClipboard> 0021 #include <QDesktopServices> 0022 #include <QGraphicsOpacityEffect> 0023 #include <QLabel> 0024 #include <QMenu> 0025 #include <QTimer> 0026 0027 class Placeholder : public QLabel 0028 { 0029 public: 0030 explicit Placeholder(QWidget *parent = nullptr) 0031 : QLabel(parent) 0032 { 0033 setAlignment(Qt::AlignCenter); 0034 setMargin(20); 0035 setWordWrap(true); 0036 // Match opacity of QML placeholder label component 0037 QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect; 0038 opacityEffect->setOpacity(0.5); 0039 setGraphicsEffect(opacityEffect); 0040 } 0041 }; 0042 0043 WelcomeView::WelcomeView(MainWindow *mainWindow, QWidget *parent) 0044 : QScrollArea(parent) 0045 , m_mainWindow(mainWindow) 0046 { 0047 setupUi(this); 0048 0049 const KAboutData aboutData = KAboutData::applicationData(); 0050 labelTitle->setText(i18n("Welcome to %1", aboutData.displayName())); 0051 labelDescription->setText(aboutData.shortDescription()); 0052 labelIcon->setPixmap(aboutData.programLogo().value<QIcon>().pixmap(KIconLoader::SizeEnormous)); 0053 0054 m_placeholderRecentFiles = new Placeholder; 0055 m_placeholderRecentFiles->setText(i18n("No recent files")); 0056 0057 QVBoxLayout *layoutPlaceholderRecentFiles = new QVBoxLayout; 0058 layoutPlaceholderRecentFiles->addWidget(m_placeholderRecentFiles); 0059 listViewRecentFiles->setLayout(layoutPlaceholderRecentFiles); 0060 0061 m_recentFilesModel = new RecentFilesModel(this); 0062 connect(m_recentFilesModel, &RecentFilesModel::modelReset, this, [this]() { 0063 const bool noRecentFiles = m_recentFilesModel->rowCount() == 0; 0064 buttonClearRecentFiles->setDisabled(noRecentFiles); 0065 m_placeholderRecentFiles->setVisible(noRecentFiles); 0066 }); 0067 0068 KRecentFilesMenu *recentFilesMenu = m_mainWindow->recentFilesMenu(); 0069 m_recentFilesModel->refresh(recentFilesMenu->recentFiles()); 0070 connect(recentFilesMenu, &KRecentFilesMenu::recentFilesChanged, this, [this, recentFilesMenu]() { 0071 m_recentFilesModel->refresh(recentFilesMenu->recentFiles()); 0072 }); 0073 0074 listViewRecentFiles->setModel(m_recentFilesModel); 0075 connect(listViewRecentFiles, &QListView::customContextMenuRequested, this, &WelcomeView::onRecentFilesContextMenuRequested); 0076 connect(listViewRecentFiles, &QListView::activated, this, [this](const QModelIndex &index) { 0077 if (index.isValid()) { 0078 const QUrl url = m_recentFilesModel->url(index); 0079 Q_ASSERT(url.isValid()); 0080 m_mainWindow->openUrl(url); 0081 } 0082 }); 0083 0084 connect(buttonNewArchive, SIGNAL(clicked()), m_mainWindow, SLOT(newArchive())); 0085 connect(buttonOpenArchive, SIGNAL(clicked()), m_mainWindow, SLOT(openArchive())); 0086 connect(buttonClearRecentFiles, &QPushButton::clicked, recentFilesMenu, &KRecentFilesMenu::clearRecentFiles); 0087 0088 connect(labelHomepage, qOverload<>(&KUrlLabel::leftClickedUrl), this, [aboutData]() { 0089 QDesktopServices::openUrl(QUrl(aboutData.homepage())); 0090 }); 0091 connect(labelHandbook, qOverload<>(&KUrlLabel::leftClickedUrl), m_mainWindow, &MainWindow::appHelpActivated); 0092 connect(buttonClose, &QPushButton::clicked, m_mainWindow, &MainWindow::hideWelcomeScreen); 0093 0094 static const char showOnStartupKey[] = "ShowWelcomeScreenOnStartup"; 0095 KConfigGroup configGroup = KSharedConfig::openConfig()->group(QStringLiteral("General")); 0096 checkBoxShowOnStartup->setChecked(configGroup.readEntry(showOnStartupKey, true)); 0097 connect(checkBoxShowOnStartup, &QCheckBox::toggled, this, [configGroup](bool checked) mutable { 0098 configGroup.writeEntry(showOnStartupKey, checked); 0099 }); 0100 0101 updateFonts(); 0102 updateButtons(); 0103 } 0104 0105 bool WelcomeView::event(QEvent *event) 0106 { 0107 switch (event->type()) { 0108 case QEvent::FontChange: 0109 updateFonts(); 0110 updateButtons(); 0111 break; 0112 case QEvent::Resize: 0113 if (updateLayout()) { 0114 return true; 0115 } 0116 break; 0117 default: 0118 break; 0119 } 0120 0121 return QScrollArea::event(event); 0122 } 0123 0124 void WelcomeView::resizeEvent(QResizeEvent *event) 0125 { 0126 QScrollArea::resizeEvent(event); 0127 0128 updateLayout(); 0129 } 0130 0131 void WelcomeView::onRecentFilesContextMenuRequested(const QPoint &pos) 0132 { 0133 const QModelIndex index = listViewRecentFiles->indexAt(pos); 0134 if (!index.isValid()) { 0135 return; 0136 } 0137 0138 const QUrl url = m_recentFilesModel->url(index); 0139 Q_ASSERT(url.isValid()); 0140 0141 QMenu contextMenu; 0142 0143 QAction *action = contextMenu.addAction(i18n("Copy &Location")); 0144 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy-path"))); 0145 connect(action, &QAction::triggered, this, [url]() { 0146 qApp->clipboard()->setText(url.toString(QUrl::PreferLocalFile)); 0147 }); 0148 0149 action = contextMenu.addAction(i18n("&Open Containing Folder")); 0150 action->setEnabled(url.isLocalFile()); 0151 action->setIcon(QIcon::fromTheme(QStringLiteral("document-open-folder"))); 0152 connect(action, &QAction::triggered, this, [url]() { 0153 KIO::highlightInFileManager({url}); 0154 }); 0155 0156 action = contextMenu.addAction(i18n("&Remove")); 0157 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0158 connect(action, &QAction::triggered, this, [this, url]() { 0159 KRecentFilesMenu *recentFilesMenu = m_mainWindow->recentFilesMenu(); 0160 recentFilesMenu->removeUrl(url); 0161 m_recentFilesModel->refresh(recentFilesMenu->recentFiles()); 0162 }); 0163 0164 contextMenu.exec(listViewRecentFiles->mapToGlobal(pos)); 0165 } 0166 0167 void WelcomeView::updateButtons() 0168 { 0169 QVector<QPushButton *> buttons{buttonNewArchive, buttonOpenArchive}; 0170 const int maxWidth = std::accumulate(buttons.cbegin(), buttons.cend(), 0, [](int maxWidth, const QPushButton *button) { 0171 return std::max(maxWidth, button->sizeHint().width()); 0172 }); 0173 for (QPushButton *button : std::as_const(buttons)) { 0174 button->setFixedWidth(maxWidth); 0175 } 0176 } 0177 0178 void WelcomeView::updateFonts() 0179 { 0180 QFont titleFont = font(); 0181 titleFont.setPointSize(titleFont.pointSize() + 6); 0182 titleFont.setWeight(QFont::Bold); 0183 labelTitle->setFont(titleFont); 0184 0185 QFont panelTitleFont = font(); 0186 panelTitleFont.setPointSize(panelTitleFont.pointSize() + 2); 0187 labelRecentFiles->setFont(panelTitleFont); 0188 labelHelp->setFont(panelTitleFont); 0189 0190 QFont placeholderFont = font(); 0191 placeholderFont.setPointSize(qRound(placeholderFont.pointSize() * 1.3)); 0192 m_placeholderRecentFiles->setFont(placeholderFont); 0193 } 0194 0195 bool WelcomeView::updateLayout() 0196 { 0197 // Align labelHelp with labelRecentFiles 0198 labelHelp->setMinimumHeight(labelRecentFiles->height()); 0199 0200 bool result = false; 0201 0202 // show/hide widgetHeader depending on the view height 0203 if (widgetHeader->isVisible()) { 0204 if (height() <= frameContent->height() + widgetClose->height()) { 0205 widgetHeader->hide(); 0206 result = true; 0207 } 0208 } else { 0209 const int implicitHeight = frameContent->height() + widgetHeader->height() + layoutContent->spacing() + widgetClose->height(); 0210 if (height() > implicitHeight) { 0211 widgetHeader->show(); 0212 result = true; 0213 } 0214 } 0215 0216 // show/hide widgetHelp depending on the view height 0217 if (widgetHelp->isVisible()) { 0218 if (width() <= frameContent->width() + widgetClose->width()) { 0219 widgetHelp->hide(); 0220 result = true; 0221 } 0222 } else { 0223 const int implicitWidth = frameContent->width() + widgetHelp->width() + layoutPanels->spacing() + widgetClose->width(); 0224 if (width() > implicitWidth) { 0225 widgetHelp->show(); 0226 return true; 0227 } 0228 } 0229 0230 return result; 0231 } 0232 0233 #include "moc_welcomeview.cpp"