11#include <QDesktopServices>
15#include <QTemporaryFile>
17#include <QNetworkAccessManager>
19#include <QDomDocument>
29#include "KConfigGroup"
30#include "KSharedConfig"
33#include <QListWidgetItem>
51#include <QCoreApplication>
57#include "config-updaters.h"
67#include <klocalizedstring.h>
86#include <QFontMetrics>
87#include <QPaintDevice>
89#include <QPainterPath>
90#include <QRandomGenerator>
97 Q_EMIT setChecked(
true);
107 : QStyledItemDelegate(parent)
116 QSize
sizeHint(
const QStyleOptionViewItem &option,
const QModelIndex &)
const override
118 return QSize(option.rect.width(),
itemHeight);
130 devBuildLabel->setVisible(
false);
131 updaterFrame->setVisible(
false);
132 versionNotificationLabel->setVisible(
false);
133 bnVersionUpdate->setVisible(
false);
134 bnErrorDetails->setVisible(
false);
137 recentDocumentsListView->setDragEnabled(
false);
138 recentDocumentsListView->viewport()->setAutoFillBackground(
false);
139 recentDocumentsListView->setSpacing(2);
140 recentDocumentsListView->installEventFilter(
this);
141 recentDocumentsListView->setViewMode(QListView::IconMode);
142 recentDocumentsListView->setSelectionMode(QAbstractItemView::NoSelection);
148 recentDocumentsListView->setVerticalScrollMode(QListView::ScrollPerPixel);
149 recentDocumentsListView->verticalScrollBar()->setSingleStep(50);
156 recentDocumentsListView->setContextMenuPolicy(Qt::CustomContextMenu);
160 QMenu *newsOptionsMenu =
new QMenu(
this);
161 newsOptionsMenu->setToolTipsVisible(
true);
163 newsOptionsMenu->addAction(showNewsAction);
164 showNewsAction->setToolTip(i18n(
"Show news about Krita: this needs internet to retrieve information from the krita.org website"));
165 showNewsAction->setCheckable(
true);
167 newsOptionsMenu->addSection(i18n(
"Language"));
168 QAction *newsInfoAction = newsOptionsMenu->addAction(i18n(
"English news is always up to date."));
169 newsInfoAction->setEnabled(
false);
172 btnNewsOptions->setMenu(newsOptionsMenu);
176 connect(showNewsAction, SIGNAL(toggled(
bool)), newsWidget, SLOT(setVisible(
bool)));
177 connect(showNewsAction, SIGNAL(toggled(
bool)), labelNoFeed, SLOT(setHidden(
bool)));
178 connect(showNewsAction, SIGNAL(toggled(
bool)), newsWidget, SLOT(toggleNews(
bool)));
179 connect(labelNoFeed, SIGNAL(linkActivated(QString)), showNewsAction, SLOT(enableFromLink(QString)));
181#ifdef ENABLE_UPDATERS
182 connect(showNewsAction, SIGNAL(toggled(
bool)),
this, SLOT(slotToggleUpdateChecks(
bool)));
185 supporterBadge->hide();
186 wdgAndroidSupportBanner->hide();
196#ifdef ENABLE_UPDATERS
206#if defined Q_OS_LINUX
207 if (!qEnvironmentVariableIsSet(
"SteamAppId")) {
208 if (qEnvironmentVariableIsSet(
"APPIMAGE")) {
214#elif defined Q_OS_WIN
225 if (!m_versionUpdater.isNull()) {
226 connect(bnVersionUpdate, SIGNAL(clicked()),
this, SLOT(slotRunVersionUpdate()));
227 connect(bnErrorDetails, SIGNAL(clicked()),
this, SLOT(slotShowUpdaterErrorDetails()));
228 connect(m_versionUpdater.data(), SIGNAL(sigUpdateCheckStateChange(
KisUpdaterStatus)),
232 m_versionUpdater->checkForUpdate();
244 setAcceptDrops(
true);
260 connect(recentDocumentsListView, SIGNAL(clicked(QModelIndex)),
this, SLOT(
recentDocumentClicked(QModelIndex)));
265 connect(clearRecentFilesLink, SIGNAL(clicked(
bool)), mainWin, SLOT(clearRecentFiles()));
268 connect(pasteAction, SIGNAL(triggered()),
this, SLOT(
slotPaste()));
277 recentDocumentsListView->setModel(&recentFilesModel->
model());
286 QString dropFrameStyle = QStringLiteral(
"QFrame#dropAreaIndicator { border: 2px solid transparent }");
287 dropFrameBorder->setStyleSheet(dropFrameStyle);
289 QColor
textColor = qApp->palette().color(QPalette::Text);
294 QString dropFrameStyle = QString(
"QFrame#dropAreaIndicator { border: 2px dotted ").append(
blendedColor.name()).append(
" }") ;
295 dropFrameBorder->setStyleSheet(dropFrameStyle);
301 textColor = qApp->palette().color(QPalette::Text);
328 dropFrameBorder->setObjectName(
"dropAreaIndicator");
329 QString dropFrameStyle = QString(
"QFrame#dropAreaIndicator { border: 4px dotted ").append(
blendedColor.name()).append(
"}");
330 dropFrameBorder->setStyleSheet(dropFrameStyle);
336 openFileLink->setIconSize(QSize(48, 48));
337 newFileLink->setIconSize(QSize(48, 48));
343 btnNewsOptions->setFlat(
true);
354 userCommunityLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://krita-artists.org\">")
355 .append(i18n(
"User Community")).append(
"</a>"));
357 gettingStartedLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://docs.krita.org/user_manual/getting_started.html\">")
358 .append(i18n(
"Getting Started")).append(
"</a>"));
360 manualLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://docs.krita.org\">")
361 .append(i18n(
"User Manual")).append(
"</a>"));
363 supportKritaLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://krita.org/support-us/donations?" +
analyticsString +
"donations" +
"\">")
364 .append(i18n(
"Support Krita")).append(
"</a>"));
366 kritaWebsiteLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://www.krita.org?" +
analyticsString +
"marketing-site" +
"\">")
367 .append(i18n(
"Krita Website")).append(
"</a>"));
369 sourceCodeLink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://invent.kde.org/graphics/krita\">")
370 .append(i18n(
"Source Code")).append(
"</a>"));
372 poweredByKDELink->setText(QString(
"<a style=\"color: " +
blendedColor.name() +
" \" href=\"https://userbase.kde.org/What_is_KDE\">")
373 .append(i18n(
"Powered by KDE")).append(
"</a>"));
375 QString translationNoFeed = i18n(
"You can <a href=\"ignored\" style=\"color: COLOR_PLACEHOLDER; text-decoration: underline;\">enable news</a> from krita.org in various languages with the menu above");
376 labelNoFeed->setText(translationNoFeed.replace(
"COLOR_PLACEHOLDER",
blendedColor.name()));
379 const QString &faintTextStyle =
"QWidget{color: " + faintTextColor.name() +
"}";
380 labelNoRecentDocs->setStyleSheet(faintTextStyle);
381 labelNoFeed->setStyleSheet(faintTextStyle);
384 const QString &frameQss =
"{border: 1px solid " + frameColor.name() +
"}";
385 recentDocsStackedWidget->setStyleSheet(
"QStackedWidget#recentDocsStackedWidget" + frameQss);
386 newsFrame->setStyleSheet(
"QFrame#newsFrame" + frameQss);
391#ifdef ENABLE_UPDATERS
392 updateVersionUpdaterFrame();
398 supportKritaLink->hide();
399 supportKritaIcon->hide();
400 labelSupportText->hide();
401 kritaWebsiteLink->hide();
402 kritaWebsiteIcon->hide();
410 if (event->mimeData()->hasUrls() ||
411 event->mimeData()->hasFormat(
"application/x-krita-node-internal-pointer") ||
412 event->mimeData()->hasFormat(
"application/x-qt-image")) {
413 return event->accept();
416 return event->ignore();
423 if (event->mimeData()->hasUrls() && !event->mimeData()->urls().empty()) {
424 Q_FOREACH (
const QUrl &url, event->mimeData()->urls()) {
425 if (url.toLocalFile().endsWith(
".bundle", Qt::CaseInsensitive)) {
428 qWarning() <<
"Could not install bundle" << url.toLocalFile();
430 }
else if (!url.isLocalFile()) {
431 QScopedPointer<QTemporaryFile>
tmp(
new QTemporaryFile());
432 tmp->setFileName(url.fileName());
437 qWarning() <<
"Fetching" << url <<
"failed";
440 const auto localUrl = QUrl::fromLocalFile(
tmp->fileName());
454 if (event->mimeData()->hasUrls() ||
455 event->mimeData()->hasFormat(
"application/x-krita-node-internal-pointer") ||
456 event->mimeData()->hasFormat(
"application/x-qt-image")) {
457 return event->accept();
460 return event->ignore();
471 if (event->type() == QEvent::FontChange) {
478 if (watched == recentDocumentsListView && event->type() == QEvent::Leave) {
479 recentDocumentsListView->clearSelection();
481 return QWidget::eventFilter(watched, event);
486QString getAutoNewsLang()
489 const QStringList uiLangs = KLocalizedString::languages();
490 QString autoNewsLang = uiLangs.first();
491 if (autoNewsLang.isEmpty()) {
493 autoNewsLang = QString(
"en");
494 }
else if (autoNewsLang ==
"ja") {
495 return QString(
"jp");
496 }
else if (autoNewsLang ==
"zh_CN") {
497 return QString(
"zh");
498 }
else if (autoNewsLang ==
"zh_TW") {
499 return QString(
"zh-tw");
500 }
else if (autoNewsLang ==
"zh_HK") {
501 return QString(
"zh-hk");
502 }
else if (autoNewsLang ==
"en" || autoNewsLang ==
"en_US" || autoNewsLang ==
"en_GB") {
503 return QString(
"en");
519 const QString siteCode;
522 static const std::array<Lang, 22> newsLangs = {{
523 {QString(
"en"), QStringLiteral(
"English")},
524 {QString(
"jp"), QStringLiteral(
"日本語")},
525 {QString(
"zh"), QStringLiteral(
"中文 (简体)")},
526 {QString(
"zh-tw"), QStringLiteral(
"中文 (台灣正體)")},
527 {QString(
"zh-hk"), QStringLiteral(
"廣東話 (香港)")},
528 {QString(
"ca"), QStringLiteral(
"Català")},
529 {QString(
"ca@valencia"), QStringLiteral(
"Català de Valencia")},
530 {QString(
"cs"), QStringLiteral(
"Čeština")},
531 {QString(
"de"), QStringLiteral(
"Deutsch")},
532 {QString(
"eo"), QStringLiteral(
"Esperanto")},
533 {QString(
"es"), QStringLiteral(
"Español")},
534 {QString(
"eu"), QStringLiteral(
"Euskara")},
535 {QString(
"fr"), QStringLiteral(
"Français")},
536 {QString(
"it"), QStringLiteral(
"Italiano")},
537 {QString(
"lt"), QStringLiteral(
"lietuvių")},
538 {QString(
"nl"), QStringLiteral(
"Nederlands")},
539 {QString(
"pt"), QStringLiteral(
"Português")},
540 {QString(
"sk"), QStringLiteral(
"Slovenský")},
541 {QString(
"sl"), QStringLiteral(
"Slovenski")},
542 {QString(
"sv"), QStringLiteral(
"Svenska")},
543 {QString(
"tr"), QStringLiteral(
"Türkçe")},
544 {QString(
"uk"), QStringLiteral(
"Українська")}
547 static const QString newsLangConfigName = QStringLiteral(
"FetchNewsLanguages");
553 auto languagesList = cfg.
readList<QString>(newsLangConfigName);
554 *enabledNewsLangs = QSet(languagesList.begin(), languagesList.end());
558 if (enabledNewsLangs->isEmpty()) {
559 enabledNewsLangs->insert(QString(getAutoNewsLang()));
562 for (
const auto &lang : newsLangs) {
563 QAction *langItem = newsOptionsMenu->addAction(lang.name);
564 langItem->setCheckable(
true);
567 const QString code = lang.siteCode;
568 connect(langItem, &QAction::toggled, newsWidget, [=](
bool checked) {
569 newsWidget->toggleNewsLanguage(code, checked);
573 if (enabledNewsLangs->contains(code)) {
574 langItem->setChecked(
true);
579 connect(langItem, &QAction::toggled, [=](
bool checked) {
585 enabledNewsLangs->insert(QString(code));
587 enabledNewsLangs->remove(QString(code));
589 cfg.
writeList(newsLangConfigName, enabledNewsLangs->values());
598 QString devBuildLabelText = QString(
"<a style=\"color: " +
600 " \" href=\"https://docs.krita.org/en/untranslatable_pages/triaging_bugs.html?"
602 .append(i18n(
"DEV BUILD")).append(
"</a>");
604 devBuildLabel->setText(devBuildLabelText);
605 devBuildIcon->setVisible(
true);
606 devBuildLabel->setVisible(
true);
608 devBuildIcon->setVisible(
false);
609 devBuildLabel->setVisible(
false);
616 QString shortcutText = action->shortcut().toString(QKeySequence::NativeText);
617 if (shortcutText.isEmpty()) {
618 label->setText(QString());
620 label->setText(QStringLiteral(
"(%1)").arg(shortcutText));
632 QString fileUrl = index.data(Qt::ToolTipRole).toString();
639 QModelIndex index = recentDocumentsListView->indexAt(pos);
640 QAction *actionForget = 0;
641 if (index.isValid()) {
642 actionForget =
new QAction(i18n(
"Forget \"%1\"", index.data(Qt::DisplayRole).toString()), &contextMenu);
643 contextMenu.addAction(actionForget);
645 QAction *triggered = contextMenu.exec(recentDocumentsListView->mapToGlobal(pos));
647 if (index.isValid() && triggered == actionForget) {
669 if (!this->isVisible())
686 const bool modelIsEmpty = recentFilesModel->
model().rowCount() == 0;
689 recentDocsStackedWidget->setCurrentWidget(labelNoRecentDocs);
691 recentDocsStackedWidget->setCurrentWidget(recentDocumentsListView);
693 clearRecentFilesLink->setVisible(!modelIsEmpty);
696#ifdef ENABLE_UPDATERS
697void KisWelcomePageWidget::slotToggleUpdateChecks(
bool state)
699 if (m_versionUpdater.isNull()) {
706 m_versionUpdater->checkForUpdate();
709 updateVersionUpdaterFrame();
711void KisWelcomePageWidget::slotRunVersionUpdate()
713 if (m_versionUpdater.isNull()) {
718 m_versionUpdater->doUpdate();
722void KisWelcomePageWidget::slotSetUpdateStatus(
KisUpdaterStatus updateStatus)
724 m_updaterStatus = updateStatus;
725 updateVersionUpdaterFrame();
728void KisWelcomePageWidget::slotShowUpdaterErrorDetails()
730 QMessageBox::warning(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), m_updaterStatus.updaterOutput());
733void KisWelcomePageWidget::updateVersionUpdaterFrame()
735 updaterFrame->setVisible(
false);
736 versionNotificationLabel->setVisible(
false);
737 bnVersionUpdate->setVisible(
false);
738 bnErrorDetails->setVisible(
false);
744 QString versionLabelText;
747 updaterFrame->setVisible(
true);
748 updaterFrame->setEnabled(
true);
749 versionLabelText = i18n(
"New version of Krita is available.");
750 versionNotificationLabel->setVisible(
true);
753 if (m_versionUpdater->hasUpdateCapability()) {
754 bnVersionUpdate->setVisible(
true);
757 QString downloadLink = QString(
" <a style=\"color: %1; text-decoration: underline\" href=\"%2?%3\">Download Krita %4</a>")
759 .arg(m_updaterStatus.downloadLink())
761 .arg(m_updaterStatus.availableVersion());
763 versionLabelText.append(downloadLink);
774 updaterFrame->setVisible(
false);
777 updaterFrame->setVisible(
true);
778 versionLabelText = i18n(
"An error occurred during the update");
779 versionNotificationLabel->setVisible(
true);
780 bnErrorDetails->setVisible(
true);
783 updaterFrame->setVisible(
true);
784 versionLabelText = QString(
"<b>%1</b> %2").arg(i18n(
"Restart is required.")).arg(m_updaterStatus.details());
785 versionNotificationLabel->setVisible(
true);
789 versionNotificationLabel->setText(versionLabelText);
797void KisWelcomePageWidget::initDonations()
800 if (!androidDonations) {
801 qWarning(
"KisWelcomePage::initDonations: androidDonations is null");
806 int bannerIndex = QRandomGenerator::global()->bounded(1, 5);
811 qreal rh = 1.0 - ry * 2.0;
814 switch (bannerIndex) {
818 rw = 1.0 - rx - rwpad;
826 qWarning(
"Unhandled banner index %d", bannerIndex);
828 rw = 1.0 - rwpad * 2.0;
832 QString welcomeBannerPath =
833 QStandardPaths::locate(QStandardPaths::AppDataLocation,
834 QStringLiteral(
"share/krita/donation/welcomebanner%1.jpg").arg(bannerIndex));
835 QPixmap welcomeBannerPixmap(welcomeBannerPath);
837 if (welcomeBannerPixmap.isNull()) {
838 qWarning(
"KisWelcomePage::initDonations: failed to load welcome banner from '%s'",
839 qUtf8Printable(welcomeBannerPath));
843 i18n(
"Become a Supporter!"),
844 i18n(
"Support Krita!"),
847 i18n(
"Supporters get brush packs and more."),
848 i18n(
"Contributions keep development going."),
850 QString headline = headlines[QRandomGenerator::global()->bounded(headlines.size())];
851 QString subtitle = subtitles[QRandomGenerator::global()->bounded(subtitles.size())];
859 QPainter painter(&welcomeBannerPixmap);
860 painter.setRenderHint(QPainter::Antialiasing);
861 painter.setRenderHint(QPainter::TextAntialiasing);
863 QPen pen(Qt::black, 12.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
864 QBrush brush(Qt::white);
866 qreal verticalSeparation = 40.0;
869 QFont currentFont = font();
870 currentFont.setPointSize(100);
871 currentFont.setBold(
false);
872 QPainterPath topPath;
873 topPath.addText(0, 0, currentFont, headline);
874 QRectF topBounds = topPath.boundingRect();
877 currentFont.setPointSize(60);
878 currentFont.setBold(
true);
879 QPainterPath bottomPath;
880 bottomPath.addText(0, 0, currentFont, subtitle);
881 QRectF bottomBounds = bottomPath.boundingRect();
885 qreal maxWidth = qMax(topBounds.width(), bottomBounds.width());
886 qreal topOffsetX = (maxWidth - topBounds.width()) / 2.0;
887 qreal bottomOffsetX = (maxWidth - bottomBounds.width()) / 2.0;
889 QTransform topTransform;
890 topTransform.translate(topOffsetX - topBounds.left(), -topBounds.top());
891 topPath = topTransform.map(topPath);
892 topPath.setFillRule(Qt::WindingFill);
894 QTransform bottomTransform;
895 bottomTransform.translate(bottomOffsetX - bottomBounds.left(),
896 topBounds.height() + verticalSeparation - bottomBounds.top());
897 bottomPath = bottomTransform.map(bottomPath);
898 bottomPath.setFillRule(Qt::WindingFill);
900 QPainterPath combinedPath;
901 combinedPath.addPath(topPath);
902 combinedPath.addPath(bottomPath);
907 qreal
w = painter.device()->width();
908 qreal
h = painter.device()->height();
909 QRect
rect(w * rx, h * ry, w * rw, h * rh);
911 QRectF combinedBounds = combinedPath.boundingRect();
912 qreal scaleX =
rect.width() / combinedBounds.width();
913 qreal scaleY =
rect.height() / combinedBounds.height();
914 qreal
scale = qMin(scaleX, scaleY);
915 qreal combinedOffsetX = (
rect.width() - (combinedBounds.width() *
scale)) / 2.0;
916 qreal combinedOffsetY = (
rect.height() - (combinedBounds.height() *
scale)) / 2.0;
918 QTransform combinedTransform;
919 combinedTransform.translate(
rect.left() + combinedOffsetX,
rect.top() + combinedOffsetY);
920 combinedTransform.scale(scale, scale);
921 combinedTransform.translate(-combinedBounds.left(), -combinedBounds.top());
922 combinedPath = combinedTransform.map(combinedPath);
923 combinedPath.setFillRule(Qt::WindingFill);
929 painter.setBrush(Qt::NoBrush);
930 painter.drawPath(combinedPath);
932 painter.setPen(Qt::NoPen);
933 painter.setBrush(brush);
934 painter.drawPath(combinedPath);
936 QSize welcomeBannerSize = welcomeBannerPixmap.size().scaled(500, 100, Qt::KeepAspectRatio);
937 bnAndroidSupport->setFlat(
false);
938 bnAndroidSupport->setText(QString());
939 bnAndroidSupport->setContentsMargins(0, 0, 0, 0);
940 bnAndroidSupport->setIcon(QIcon(welcomeBannerPixmap));
941 bnAndroidSupport->setIconSize(welcomeBannerSize);
942 bnAndroidSupport->setFixedSize(welcomeBannerSize);
946 connect(bnAndroidSupporterManage,
947 &QPushButton::clicked,
951 QString badgePath = QStandardPaths::locate(QStandardPaths::AppDataLocation,
"share/krita/donation/banner.png");
952 QPixmap badgePixmap(badgePath);
953 if (badgePixmap.isNull()) {
954 qWarning(
"KisWelcomePage::initDonations: failed to load badge from '%s'", qUtf8Printable(badgePath));
956 supporterBadge->setPixmap(badgePixmap);
959 connect(androidDonations, SIGNAL(sigStateChanged()),
this, SLOT(slotUpdateDonationState()));
960 slotUpdateDonationState();
963void KisWelcomePageWidget::slotUpdateDonationState()
965 bool badgeVisible =
false;
966 QWidget *pageVisible = pgSupportMessage;
969 if (androidDonations) {
971 switch (androidDonations->
state()) {
973 pageVisible = pgAndroidSupporter;
976 pageVisible =
nullptr;
982 qWarning(
"KisWelcomePageWidget::slotUpdateDonationState: android donations is null");
986 stkSupport->setCurrentWidget(pageVisible);
987 wdgAndroidSupportBanner->hide();
991 wdgAndroidSupportBanner->show();
994 supporterBadge->setVisible(badgeVisible);
1000 QFont larger = font();
1003 if (larger.pixelSize() == -1) {
1004 larger.setPointSizeF(larger.pointSizeF() * ratio);
1006 larger.setPixelSize(qRound(larger.pixelSize() * ratio));
A KisActionManager class keeps track of KisActions. These actions are always associated with the GUI....
KisAction * actionByName(const QString &name) const
void slotStartDonationFlow()
bool shouldShowSupporterBadge() const
static KisAndroidDonations * instance()
void sigShowDonationManagementDialogRequested()
static KisClipboard * instance()
void writeList(const QString &name, const QList< T > &value)
QList< T > readList(const QString &name, const QList< T > &defaultValue=QList< T >())
T readEntry(const QString &name, const T &defaultValue=T())
void SelectPage(Page page)
bool installBundle(const QString &fileName) const
Copy the given file into the bundle directory.
bool openDocument(const QString &path, OpenFlags flags)
KisViewManager * viewManager
void slotFileOpen(bool isImporting=false)
void removeRecentFile(QString url)
void dragMoveEvent(QDragMoveEvent *event) override
static constexpr const int ICON_SIZE_LENGTH
QStandardItemModel & model()
static KisRecentDocumentsModelWrapper * instance()
The KisRemoteFileFetcher class can fetch a remote file and blocks until the file is downloaded.
bool fetchFile(const QUrl &remote, QIODevice *io)
fetch the image. Shows a progress dialog
static void log(const QString &message)
Logs with date/time.
KisActionManager * actionManager() const
void recentDocumentClicked(QModelIndex index)
KisWelcomePageWidget(QWidget *parent)
void dragEnterEvent(QDragEnterEvent *event) override
void setupNewsLangSelection(QMenu *newsOptionMenu)
bool isDevelopmentBuild()
void slotNewFileClicked()
bool eventFilter(QObject *watched, QEvent *event) override
static void updateShortcutLink(QToolButton *button, QLabel *label, QAction *action)
void dropEvent(QDropEvent *event) override
void slotUpdateThemeColors()
void slotScrollerStateChanged(QScroller::State state)
void slotOpenFileClicked()
void dragLeaveEvent(QDragLeaveEvent *event) override
void changeEvent(QEvent *event) override
KisMainWindow * m_mainWindow
void showDevVersionHighlight()
void slotRecentFilesModelIsUpToDate()
const QString analyticsString
void setMainWindow(KisMainWindow *m_mainWindow)
void slotRecentDocContextMenuRequest(const QPoint &pos)
void showDropAreaIndicator(bool show)
~KisWelcomePageWidget() override
void dragMoveEvent(QDragMoveEvent *event) override
RecentItemDelegate(QObject *parent=0)
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const override
void setItemHeight(int itemHeight)
void enableFromLink(QString unused_url)
QString button(const QWheelEvent &ev)
QIcon loadIcon(const QString &name)
void updateIcon(QAbstractButton *button)
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)
bool isRunningInPackage()
KRITAVERSION_EXPORT bool isDevelopersBuild()