diff --git a/libs/ui/KisAutoSaveRecoveryDialog.cpp b/libs/ui/KisAutoSaveRecoveryDialog.cpp index 2769ecef88..2ae547230a 100644 --- a/libs/ui/KisAutoSaveRecoveryDialog.cpp +++ b/libs/ui/KisAutoSaveRecoveryDialog.cpp @@ -1,279 +1,279 @@ /* This file is part of the KDE project Copyright (C) 2012 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisAutoSaveRecoveryDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct FileItem { FileItem() : checked(true) {} QImage thumbnail; QString name; QString date; bool checked; }; class FileItemDelegate : public KWidgetItemDelegate { public: FileItemDelegate(QAbstractItemView *itemView, KisAutoSaveRecoveryDialog *dlg) : KWidgetItemDelegate(itemView, dlg) , m_parent(dlg) { } QList createItemWidgets(const QModelIndex& index) const override { // a lump of coal and a piece of elastic will get you through the world QWidget *page = new QWidget; QHBoxLayout *layout = new QHBoxLayout(page); QCheckBox *checkBox = new QCheckBox; checkBox->setProperty("fileitem", index.data()); connect(checkBox, SIGNAL(toggled(bool)), m_parent, SLOT(toggleFileItem(bool))); QLabel *thumbnail = new QLabel; QLabel *filename = new QLabel; QLabel *dateModified = new QLabel; layout->addWidget(checkBox); layout->addWidget(thumbnail); layout->addWidget(filename); layout->addWidget(dateModified); page->setFixedSize(600, 200); return QList() << page; } void updateItemWidgets(const QList widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const override { FileItem *fileItem = (FileItem*)index.data().value(); QWidget* page= widgets[0]; QHBoxLayout* layout = qobject_cast(page->layout()); QCheckBox *checkBox = qobject_cast(layout->itemAt(0)->widget()); QLabel *thumbnail = qobject_cast(layout->itemAt(1)->widget()); QLabel *filename = qobject_cast(layout->itemAt(2)->widget()); QLabel *modified = qobject_cast(layout->itemAt(3)->widget()); checkBox->setChecked(fileItem->checked); thumbnail->setPixmap(QPixmap::fromImage(fileItem->thumbnail)); filename->setText(fileItem->name); modified->setText(fileItem->date); // move the page _up_ otherwise it will draw relative to the actual position page->setGeometry(option.rect.translated(0, -option.rect.y())); } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const override { //paint background for selected or hovered item QStyleOptionViewItem opt = option; itemView()->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, 0); } QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const override { return QSize(600, 200); } KisAutoSaveRecoveryDialog *m_parent; }; class KisAutoSaveRecoveryDialog::FileItemModel : public QAbstractListModel { public: FileItemModel(QList fileItems, QObject *parent) : QAbstractListModel(parent) , m_fileItems(fileItems){} ~FileItemModel() override { qDeleteAll(m_fileItems); m_fileItems.clear(); } int rowCount(const QModelIndex &/*parent*/) const override { return m_fileItems.size(); } Qt::ItemFlags flags(const QModelIndex& /*index*/) const override { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; return flags; } QVariant data(const QModelIndex& index, int role) const override { if (index.isValid() && index.row() < m_fileItems.size()) { FileItem *item = m_fileItems.at(index.row()); switch (role) { case Qt::DisplayRole: { return QVariant::fromValue((void*)item); } case Qt::SizeHintRole: return QSize(600, 200); } } return QVariant(); } bool setData(const QModelIndex& index, const QVariant& /*value*/, int role) override { if (index.isValid() && index.row() < m_fileItems.size()) { if (role == Qt::CheckStateRole) { m_fileItems.at(index.row())->checked = !m_fileItems.at(index.row())->checked; return true; } } return false; } QList m_fileItems; }; KisAutoSaveRecoveryDialog::KisAutoSaveRecoveryDialog(const QStringList &filenames, QWidget *parent) : KoDialog(parent) { setCaption(i18nc("@title:window", "Recover Files")); setButtons( KoDialog::Ok | KoDialog::Cancel | KoDialog::User1 ); setButtonText(KoDialog::User1, i18n("Discard All")); setMinimumSize(650, 500); QWidget *page = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(page); if (filenames.size() == 1) { layout->addWidget(new QLabel(i18n("The following autosave file can be recovered:"))); } else { layout->addWidget(new QLabel(i18n("The following autosave files can be recovered:"))); } m_listView = new QListView(); m_listView->setAcceptDrops(false); KWidgetItemDelegate *delegate = new FileItemDelegate(m_listView, this); m_listView->setItemDelegate(delegate); QList fileItems; Q_FOREACH (const QString &filename, filenames) { FileItem *file = new FileItem(); file->name = filename; #ifdef Q_OS_WIN QString path = QDir::tempPath() + "/" + filename; #else QString path = QDir::homePath() + "/" + filename; #endif // get thumbnail -- almost all Krita-supported formats save a thumbnail KoStore* store = KoStore::createStore(path, KoStore::Read); if (store) { - if(store->open(QString("Thumbnails/thumbnail.png")) + if (store->open(QString("Thumbnails/thumbnail.png")) || store->open(QString("preview.png"))) { // Hooray! No long delay for the user... QByteArray bytes = store->read(store->size()); store->close(); QImage img; img.loadFromData(bytes); file->thumbnail = img.scaled(QSize(200,200), Qt::KeepAspectRatio, Qt::SmoothTransformation); } delete store; } // get the date QDateTime date = QFileInfo(path).lastModified(); file->date = "(" + date.toString(Qt::LocalDate) + ")"; fileItems.append(file); } m_model = new FileItemModel(fileItems, m_listView); m_listView->setModel(m_model); layout->addWidget(m_listView); layout->addWidget(new QLabel(i18n("If you select Cancel, all recoverable files will be kept.\nIf you press OK, selected files will be recovered, the unselected files discarded."))); setMainWidget(page); setAttribute(Qt::WA_DeleteOnClose, false); connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotDeleteAll() ) ); } KisAutoSaveRecoveryDialog::~KisAutoSaveRecoveryDialog() { delete m_listView->itemDelegate(); delete m_model; delete m_listView; } void KisAutoSaveRecoveryDialog::slotDeleteAll() { foreach(FileItem* fileItem, m_model->m_fileItems) { fileItem->checked = false; } accept(); } QStringList KisAutoSaveRecoveryDialog::recoverableFiles() { QStringList files; Q_FOREACH (FileItem* fileItem, m_model->m_fileItems) { if (fileItem->checked) { files << fileItem->name; } } return files; } void KisAutoSaveRecoveryDialog::toggleFileItem(bool toggle) { // I've made better man from a piece of putty and matchstick! QVariant v = sender()->property("fileitem") ; if (v.isValid()) { FileItem *fileItem = (FileItem*)v.value(); fileItem->checked = toggle; } } diff --git a/libs/ui/KisWelcomePageWidget.cpp b/libs/ui/KisWelcomePageWidget.cpp index 00767424b1..ea493b7f1a 100644 --- a/libs/ui/KisWelcomePageWidget.cpp +++ b/libs/ui/KisWelcomePageWidget.cpp @@ -1,276 +1,278 @@ /* This file is part of the KDE project * Copyright (C) 2018 Scott Petrovic * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisWelcomePageWidget.h" #include #include #include "kis_action_manager.h" #include "kactioncollection.h" #include "kis_action.h" #include "KConfigGroup" #include "KSharedConfig" #include #include #include "kis_icon_utils.h" #include "krita_utils.h" #include "KoStore.h" KisWelcomePageWidget::KisWelcomePageWidget(QWidget *parent) { Q_UNUSED(parent); setupUi(this); recentDocumentsListView->viewport()->setAutoFillBackground(false); recentDocumentsListView->setSpacing(2); } KisWelcomePageWidget::~KisWelcomePageWidget() { } void KisWelcomePageWidget::setMainWindow(KisMainWindow* mainWin) { if (mainWin) { mainWindow = mainWin; // set the shortcut links from actions (only if a shortcut exists) if ( mainWin->viewManager()->actionManager()->actionByName("file_new")->shortcut().toString() != "") { newFileLinkShortcut->setText(QString("(") + mainWin->viewManager()->actionManager()->actionByName("file_new")->shortcut().toString() + QString(")")); } if (mainWin->viewManager()->actionManager()->actionByName("file_open")->shortcut().toString() != "") { openFileShortcut->setText(QString("(") + mainWin->viewManager()->actionManager()->actionByName("file_open")->shortcut().toString() + QString(")")); } populateRecentDocuments(); connect(recentDocumentsListView, SIGNAL(clicked(QModelIndex)), this, SLOT(recentDocumentClicked(QModelIndex))); // we need the view manager to actually call actions, so don't create the connections // until after the view manager is set connect(newFileLink, SIGNAL(clicked(bool)), this, SLOT(slotNewFileClicked())); connect(openFileLink, SIGNAL(clicked(bool)), this, SLOT(slotOpenFileClicked())); // URL link connections connect(manualLink, SIGNAL(clicked(bool)), this, SLOT(slotGoToManual())); connect(gettingStartedLink, SIGNAL(clicked(bool)), this, SLOT(slotGettingStarted())); connect(supportKritaLink, SIGNAL(clicked(bool)), this, SLOT(slotSupportKrita())); connect(userCommunityLink, SIGNAL(clicked(bool)), this, SLOT(slotUserCommunity())); connect(kritaWebsiteLink, SIGNAL(clicked(bool)), this, SLOT(slotKritaWebsite())); connect(sourceCodeLink, SIGNAL(clicked(bool)), this, SLOT(slotSourceCode())); connect(clearRecentFilesLink, SIGNAL(clicked(bool)), this, SLOT(slotClearRecentFiles())); connect(poweredByKDELink, SIGNAL(clicked(bool)), this, SLOT(slotKDESiteLink())); slotUpdateThemeColors(); } } void KisWelcomePageWidget::showDropAreaIndicator(bool show) { if (!show) { QString dropFrameStyle = "QFrame#dropAreaIndicator { border: 0px }"; dropFrameBorder->setStyleSheet(dropFrameStyle); } else { QColor textColor = qApp->palette().color(QPalette::Text); QColor backgroundColor = qApp->palette().color(QPalette::Background); QColor blendedColor = KritaUtils::blendColors(textColor, backgroundColor, 0.8); // QColor.name() turns it into a hex/web format QString dropFrameStyle = QString("QFrame#dropAreaIndicator { border: 2px dotted ").append(blendedColor.name()).append(" }") ; dropFrameBorder->setStyleSheet(dropFrameStyle); } } void KisWelcomePageWidget::slotUpdateThemeColors() { QColor textColor = qApp->palette().color(QPalette::Text); QColor backgroundColor = qApp->palette().color(QPalette::Background); // make the welcome screen labels a subtle color so it doesn't clash with the main UI elements QColor blendedColor = KritaUtils::blendColors(textColor, backgroundColor, 0.8); QString blendedStyle = QString("color: ").append(blendedColor.name()); // what labels to change the color... startTitleLabel->setStyleSheet(blendedStyle); recentDocumentsLabel->setStyleSheet(blendedStyle); helpTitleLabel->setStyleSheet(blendedStyle); manualLink->setStyleSheet(blendedStyle); gettingStartedLink->setStyleSheet(blendedStyle); supportKritaLink->setStyleSheet(blendedStyle); userCommunityLink->setStyleSheet(blendedStyle); kritaWebsiteLink->setStyleSheet(blendedStyle); sourceCodeLink->setStyleSheet(blendedStyle); newFileLinkShortcut->setStyleSheet(blendedStyle); openFileShortcut->setStyleSheet(blendedStyle); clearRecentFilesLink->setStyleSheet(blendedStyle); poweredByKDELink->setStyleSheet(blendedStyle); recentDocumentsListView->setStyleSheet(blendedStyle); newFileLink->setStyleSheet(blendedStyle); openFileLink->setStyleSheet(blendedStyle); // giving the drag area messaging a dotted border QString dottedBorderStyle = QString("border: 2px dotted ").append(blendedColor.name()).append("; color:").append(blendedColor.name()).append( ";"); dragImageHereLabel->setStyleSheet(dottedBorderStyle); // make drop area QFrame have a dotted line dropFrameBorder->setObjectName("dropAreaIndicator"); QString dropFrameStyle = QString("QFrame#dropAreaIndicator { border: 4px dotted ").append(blendedColor.name()).append("}"); dropFrameBorder->setStyleSheet(dropFrameStyle); // only show drop area when we have a document over the empty area showDropAreaIndicator(false); // add icons for new and open settings to make them stand out a bit more openFileLink->setIconSize(QSize(30, 30)); newFileLink->setIconSize(QSize(30, 30)); openFileLink->setIcon(KisIconUtils::loadIcon("document-open")); newFileLink->setIcon(KisIconUtils::loadIcon("document-new")); // needed for updating icon color for files that don't have a preview if (mainWindow) { populateRecentDocuments(); } } void KisWelcomePageWidget::populateRecentDocuments() { // grab recent files data recentFilesModel = new QStandardItemModel(); int recentDocumentsIterator = mainWindow->recentFilesUrls().length() > 5 ? 5 : mainWindow->recentFilesUrls().length(); // grab at most 5 for (int i = 0; i < recentDocumentsIterator; i++ ) { QStandardItem *recentItem = new QStandardItem(1,2); // 1 row, 1 column QString recentFileUrlPath = mainWindow->recentFilesUrls().at(i).toString(); QString fileName = recentFileUrlPath.split("/").last(); // get thumbnail -- almost all Krita-supported formats save a thumbnail - // this was mostly copied from the KisAutoSaveRecorvery file - QScopedPointer store( KoStore::createStore(QUrl(recentFileUrlPath), KoStore::Read) ); + // this was mostly copied from the KisAutoSaveRecovery file + QScopedPointer store(KoStore::createStore(QUrl(recentFileUrlPath), KoStore::Read)); if (store) { - if(store->open(QString("Thumbnails/thumbnail.png")) + if (store->open(QString("Thumbnails/thumbnail.png")) || store->open(QString("preview.png"))) { QByteArray bytes = store->read(store->size()); store->close(); QImage img; img.loadFromData(bytes); recentItem->setIcon(QIcon(QPixmap::fromImage(img))); - }else { + } + else { recentItem->setIcon(KisIconUtils::loadIcon("document-export")); } - } else { + } + else { recentItem->setIcon(KisIconUtils::loadIcon("document-export")); } // set the recent object with the data recentItem->setText(fileName); // what to display for the item recentItem->setToolTip(recentFileUrlPath); recentFilesModel->appendRow(recentItem); } // hide clear and Recent files title if there are none bool hasRecentFiles = mainWindow->recentFilesUrls().length() > 0; recentDocumentsLabel->setVisible(hasRecentFiles); clearRecentFilesLink->setVisible(hasRecentFiles); recentDocumentsListView->setIconSize(QSize(40, 40)); recentDocumentsListView->setModel(recentFilesModel); } void KisWelcomePageWidget::recentDocumentClicked(QModelIndex index) { QString fileUrl = index.data(Qt::ToolTipRole).toString(); mainWindow->openDocument(QUrl(fileUrl), KisMainWindow::None ); } void KisWelcomePageWidget::slotNewFileClicked() { mainWindow->slotFileNew(); } void KisWelcomePageWidget::slotOpenFileClicked() { mainWindow->slotFileOpen(); } void KisWelcomePageWidget::slotClearRecentFiles() { mainWindow->clearRecentFiles(); mainWindow->reloadRecentFileList(); populateRecentDocuments(); } void KisWelcomePageWidget::slotGoToManual() { QDesktopServices::openUrl(QUrl("https://docs.krita.org")); } void KisWelcomePageWidget::slotGettingStarted() { QDesktopServices::openUrl(QUrl("https://docs.krita.org/en/user_manual/getting_started.html")); } void KisWelcomePageWidget::slotSupportKrita() { QDesktopServices::openUrl(QUrl("https://krita.org/en/support-us/donations/")); } void KisWelcomePageWidget::slotUserCommunity() { QDesktopServices::openUrl(QUrl("https://forum.kde.org/viewforum.php?f=136")); } void KisWelcomePageWidget::slotKritaWebsite() { QDesktopServices::openUrl(QUrl("https://www.krita.org")); } void KisWelcomePageWidget::slotSourceCode() { QDesktopServices::openUrl(QUrl("https://phabricator.kde.org/source/krita/")); } void KisWelcomePageWidget::slotKDESiteLink() { QDesktopServices::openUrl(QUrl("https://userbase.kde.org/What_is_KDE")); }