15#include <QApplication>
18#include <QStandardPaths>
19#include <QDesktopServices>
24#include <QInputDialog>
27#include <QMdiSubWindow>
29#include <QMutexLocker>
37#include <QStyleFactory>
42#include <QStackedWidget>
47#include <QTemporaryDir>
49#include <QActionGroup>
52#include <kactionmenu.h>
56#include <klocalizedstring.h>
57#include <kaboutdata.h>
64#include <ktoggleaction.h>
71#include <kwindowconfig.h>
72#include <kacceleratormanager.h>
156#include <config-qmdiarea-always-show-subwindow-title.h>
165 QString
id()
const override {
166 return "sharedtooldocker";
185 , styleMenu(new KActionMenu(i18nc(
"@action:inmenu",
"Styles"), parent))
186 , dockWidgetMenu(new KActionMenu(i18nc(
"@action:inmenu",
"&Dockers"), parent))
187 , windowMenu(new KActionMenu(i18nc(
"@action:inmenu",
"&Window"), parent))
188 , documentMenu(new KActionMenu(i18nc(
"@action:inmenu",
"New &View"), parent))
189 , workspaceMenu(new KActionMenu(i18nc(
"@action:inmenu",
"Wor&kspace"), parent))
191 , widgetStack(new QStackedWidget(parent))
192 , mdiArea(new QMdiArea(parent))
196 if (
id.isNull()) this->
id = QUuid::createUuid();
198 welcomeScroller =
new QScrollArea();
199 welcomeScroller->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
200 welcomeScroller->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
201 welcomeScroller->setWidget(welcomePage);
202 welcomeScroller->setWidgetResizable(
true);
204 widgetStack->addWidget(welcomeScroller);
205 widgetStack->addWidget(mdiArea);
206 mdiArea->setTabsMovable(
true);
207 mdiArea->setActivationOrder(QMdiArea::ActivationHistoryOrder);
208 mdiArea->setDocumentMode(
true);
209 mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
210#ifdef HAVE_QMDIAREA_ALWAYS_SHOW_SUBWINDOW_TITLE
211 mdiArea->setOption(QMdiArea::AlwaysShowSubwindowNameInTitleBar);
218 qDeleteAll(toolbarList);
231 bool firstTime {
true};
232 bool windowSizeDirty {
false};
264 KActionMenu *styleMenu {
nullptr};
265 QActionGroup* styleActions {
nullptr};
268 KActionMenu *dockWidgetMenu {
nullptr};
269 KActionMenu *windowMenu {
nullptr};
270 KActionMenu *documentMenu {
nullptr};
271 KActionMenu *workspaceMenu {
nullptr};
286 QCloseEvent *deferredClosingEvent {
nullptr};
290 QScrollArea *welcomeScroller {
nullptr};
294 QStackedWidget *widgetStack {
nullptr};
296 QMdiArea *mdiArea {
nullptr};
297 QMdiSubWindow *activeSubWindow {
nullptr};
313 return viewManager->actionManager();
317 QObjectList objects = mdiArea->children();
318 Q_FOREACH (QObject *
object, objects) {
319 QTabBar *bar = qobject_cast<QTabBar*>(
object);
335 widget->setEnabled(
false);
348 KAcceleratorManager::setNoAccel(
this);
356 KConfigGroup group( KSharedConfig::openConfig(),
"theme");
360 d->windowStateConfig = KSharedConfig::openConfig()->group(
"MainWindow");
363 setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
364 setDockNestingEnabled(
true);
366 qApp->setStartDragDistance(25);
390 d->toolOptionsDocker = qobject_cast<KoToolDocker*>(
createDockWidget(&toolDockerFactory));
391 if (
d->toolOptionsDocker) {
392 d->toolOptionsDocker->toggleViewAction()->setEnabled(
true);
396 QMap<QString, QAction*> dockwidgetActions;
399 dockwidgetActions[toolbox->toggleViewAction()->text()] = toolbox->toggleViewAction();
405 dockwidgetActions[dw->toggleViewAction()->text()] = dw->toggleViewAction();
409 if (
d->toolOptionsDocker) {
410 dockwidgetActions[
d->toolOptionsDocker->toggleViewAction()->text()] =
d->toolOptionsDocker->toggleViewAction();
414 Q_FOREACH (QString title, dockwidgetActions.keys()) {
415 d->dockWidgetMenu->addAction(dockwidgetActions[title]);
420 d->styleActions =
new QActionGroup(
this);
423#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
429 Q_FOREACH (QString styleName, QStyleFactory::keys()) {
432 if (styleName.toLower().contains(
"android")) {
436 if (qgetenv(
"KRITA_NO_STYLE_OVERRIDE").isEmpty()) {
437 if (!allowableStyles.contains(styleName.toLower())) {
441 action =
new QAction(styleName,
d->styleActions);
442 action->setCheckable(
true);
443 d->actionMap.insert(styleName,
action);
444 d->styleMenu->addAction(
d->actionMap.value(styleName));
449 QString styleFromConfig = cfg.
widgetStyle().toLower();
450 QString styleToSelect = styleFromConfig ==
"" ? style()->objectName().toLower() : styleFromConfig;
452 Q_FOREACH (
auto key,
d->actionMap.keys()) {
453 if(key.toLower() == styleToSelect) {
454 d->actionMap.value(key)->setChecked(
true);
458 connect(
d->styleActions, SIGNAL(triggered(QAction*)),
470 if ((wdg->features() & QDockWidget::DockWidgetClosable) == 0) {
471 wdg->setVisible(
true);
478 if (mainwindowObserver) {
483 d->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
484 d->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
485 d->mdiArea->setTabPosition(QTabWidget::North);
486 d->mdiArea->setTabsClosable(
true);
487 d->mdiArea->setAcceptDrops(
true);
491 setCentralWidget(
d->widgetStack);
492 d->widgetStack->setCurrentIndex(0);
496 connect(
d->documentMapper, SIGNAL(mapped(QObject*)),
this, SLOT(
newView(QObject*)));
504 d->welcomePage->setMainWindow(
this);
512 QGuiApplication *app = qApp;
513 KAboutData aboutData(KAboutData::applicationData());
514 aboutData.setOrganizationDomain(app->organizationDomain().toUtf8());
531 if (helpContentsAction) {
532 actions->
addAction(helpContentsAction->objectName(), helpContentsAction);
534 if (whatsThisAction) {
535 actions->
addAction(whatsThisAction->objectName(), whatsThisAction);
537 if (reportBugAction) {
538 actions->
addAction(reportBugAction->objectName(), reportBugAction);
540 if (switchLanguageAction) {
541 actions->
addAction(switchLanguageAction->objectName(), switchLanguageAction);
543 if (aboutAppAction) {
544 actions->
addAction(aboutAppAction->objectName(), aboutAppAction);
546 if (aboutKdeAction) {
547 actions->
addAction(aboutKdeAction->objectName(), aboutKdeAction);
555 helpAction->disconnect();
560 QSet<QKeySequence> existingShortcuts;
562 if(
action->shortcut() == QKeySequence(0)) {
566 Q_ASSERT(!existingShortcuts.contains(
action->shortcut()));
567 existingShortcuts.insert(
action->shortcut());
586 Q_FOREACH (QWidget* it,
guiFactory()->containers(
"ToolBar")) {
589 KToggleAction* act =
new KToggleAction(i18n(
"Show %1 Toolbar",
toolBar->windowTitle()),
this);
591 act->setCheckedState(KGuiItem(i18n(
"Hide %1 Toolbar",
toolBar->windowTitle())));
593 act->setChecked(!
toolBar->isHidden());
596 warnUI <<
"Toolbar list contains a " << it->metaObject()->className() <<
" which is not a toolbar!";
605 d->viewManager->updateGUI();
606 d->viewManager->updateIcons();
608 QTimer::singleShot(1000, Qt::CoarseTimer,
this, SLOT(
checkSanity()));
611 using namespace std::placeholders;
612 std::function<
void (
int)> callback(
615 d->tabSwitchCompressor.reset(
620 if (cfg.
readEntry(
"CanvasOnlyActive",
false)) {
621 QString currentWorkspace = cfg.
readEntry<QString>(
"CurrentWorkspace",
"Default");
628 menuBar()->setVisible(
true);
637 setFixedSize(KisApplication::primaryScreen()->availableGeometry().size());
639 QScreen *s = QGuiApplication::primaryScreen();
640 s->setOrientationUpdateMask(Qt::LandscapeOrientation|Qt::InvertedLandscapeOrientation|Qt::PortraitOrientation|Qt::InvertedPortraitOrientation);
646 QAndroidJniObject::callStaticMethod<void>(
"org/qtproject/qt5/android/QtNative",
"setApplicationState",
"(I)V", Qt::ApplicationActive);
649 setAcceptDrops(
true);
650 QTabBar *tabBar =
d->findTabBarHACK();
652 tabBar->setElideMode(Qt::ElideRight);
655 tabBar->setExpanding(
true);
656 tabBar->setAcceptDrops(
true);
657 tabBar->setChangeCurrentOnDrag(
true);
688 delete d->viewManager;
704 if (
d->activeView == view && !subWindow)
return;
707 d->activeView->disconnect(
this);
748 QMdiSubWindow *currentSubWin =
d->mdiArea->currentSubWindow();
749 bool shouldMaximize = currentSubWin ? currentSubWin->isMaximized() :
true;
750 subwin =
d->mdiArea->addSubWindow(imageView);
751 if (shouldMaximize) {
752 subwin->setWindowState(Qt::WindowMaximized);
755 subwin->setWidget(imageView);
758 subwin->setAttribute(Qt::WA_DeleteOnClose,
true);
762 subwin->setOption(QMdiSubWindow::RubberBandMove, cfg.
readEntry<
int>(
"mdi_rubberband", cfg.
useOpenGL()));
763 subwin->setOption(QMdiSubWindow::RubberBandResize, cfg.
readEntry<
int>(
"mdi_rubberband", cfg.
useOpenGL()));
764 subwin->setWindowIcon(qApp->windowIcon());
771 if (
d->mdiArea->subWindowList().size() == 1) {
772 imageView->showMaximized();
817 if (dlgPreferences->editPreferences()) {
840 d->viewManager->showHideScrollbars();
851 d->mdiArea->setPalette(qApp->palette());
852 for (
int i=0; i<
d->mdiArea->subWindowList().size(); i++) {
853 QMdiSubWindow *window =
d->mdiArea->subWindowList().at(i);
855 window->setPalette(qApp->palette());
856 KisView *view = qobject_cast<KisView*>(window->widget());
870 objects.append(aToolBar);
871 while (!objects.isEmpty()) {
872 QWidget*
widget = qobject_cast<QWidget*>(objects.takeFirst());
874 objects.append(
widget->children());
875 widget->setPalette(qApp->palette());
884 KConfigGroup group(KSharedConfig::openConfig(),
"theme");
886 if (group.readEntry(
"Theme",
"") ==
d->themeManager->currentThemeName())
return;
889 group.writeEntry(
"Theme",
d->themeManager->currentThemeName());
894 Q_FOREACH (QWidget* topLevelWidget, qApp->topLevelWidgets()) {
895 if (topLevelWidget ==
this) {
899 if (topLevelWidget->isHidden()) {
903 KisMainWindow *topLevelMainWindow = qobject_cast<KisMainWindow*>(topLevelWidget);
904 if (topLevelMainWindow) {
909 objects.append(topLevelWidget);
910 while (!objects.isEmpty()) {
911 QWidget*
widget = qobject_cast<QWidget*>(objects.takeFirst());
913 objects.append(
widget->children());
930 QString closeButtonImageUrl;
931 QString closeButtonHoverColor;
933 closeButtonImageUrl = QStringLiteral(
":/dark_close-tab.svg");
934 closeButtonHoverColor = QStringLiteral(
"lightcoral");
936 closeButtonImageUrl = QStringLiteral(
":/light_close-tab.svg");
937 closeButtonHoverColor = QStringLiteral(
"darkred");
939 QString tabStyleSheet = QStringLiteral(R
"(
940 QTabBar::close-button {
944 QTabBar::close-button:hover {
945 background-color: %2;
947 QTabBar::close-button:pressed {
948 background-color: red;
951 QHeaderView::section {
956 .arg(closeButtonImageUrl, closeButtonHoverColor);
959 QTabBar* tabBar = d->findTabBarHACK();
961 tabBar->setStyleSheet(tabStyleSheet);
968 return centralWidget() !=
d->widgetStack;
975 QMessageBox::warning(
this, i18nc(
"@title:window",
"Krita"),
976 "Detach Canvas is unsupported on Android");
981 QWidget *outgoingWidget = centralWidget() ? takeCentralWidget() :
nullptr;
982 QWidget *incomingWidget =
d->canvasWindow->swapMainWidget(outgoingWidget);
984 if (incomingWidget) {
985 setCentralWidget(incomingWidget);
989 d->canvasWindow->show();
991 d->canvasWindow->hide();
993 d->toggleDetachCanvas->setChecked(detach);
999 return d->canvasWindow;
1014 const QString fileName = QFileInfo(documentPath).fileName();
1016 if (!fileName.isEmpty()) {
1017 d->saveAction->setToolTip(i18n(
"Save as %1", fileName));
1020 d->saveAction->setToolTip(i18n(
"Save"));
1026 Q_UNUSED(readWrite);
1027 d->actionManager()->updateGUI();
1032 if (
d->activeView) {
1033 return d->activeView;
1041 QApplication::processEvents();
1043 if (!QFile(path).exists()) {
1045 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"The file %1 does not exist.", path));
1055 if (!QFile(path).exists()) {
1056 qWarning() <<
"KisMainWindow::openDocumentInternal. Could not open:" << path;
1066 d->firstTime =
true;
1087 ( path.startsWith(QDir::tempPath())
1088 || path.startsWith(QDir::homePath())
1090 ( QFileInfo(path).fileName().startsWith(
".krita")
1091 || QFileInfo(path).fileName().startsWith(
"krita")
1095 QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
1096 if (!QFileInfo(path).exists()) {
1097 path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
1099 newdoc->
setPath(path +
"/" + newdoc->objectName() +
".kra");
1106 Q_FOREACH(QMdiSubWindow *subwindow,
d->mdiArea->subWindowList()) {
1107 KisView *view = qobject_cast<KisView*>(subwindow->widget());
1111 if (view->
document() == document) {
1122 QMdiSubWindow *subWindow)
1137 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1139 dialog.setCaption(isImporting ? i18n(
"Import Images") : i18n(
"Open Images"));
1150 KisDocument *newdoc = qobject_cast<KisDocument*>(sender());
1151 if (newdoc && newdoc->
image()) {
1155 disconnect(newdoc, SIGNAL(canceled(QString)),
this, SLOT(
slotLoadCanceled(QString)));
1164 KisDocument* doc = qobject_cast<KisDocument*>(sender());
1167 disconnect(doc, SIGNAL(canceled(QString)),
this, SLOT(
slotLoadCanceled(QString)));
1172 if (!errMsg.isEmpty()) {
1174 QMessageBox::critical(
this, i18nc(
"@title:window",
"Krita"), errMsg);
1185 KisDocument* doc = qobject_cast<KisDocument*>(sender());
1188 disconnect(doc, SIGNAL(canceled(QString)),
this, SLOT(
slotSaveCanceled(QString)));
1191 if (
d->deferredClosingEvent) {
1198 std::unique_lock<QMutex> l(
d->savingEntryMutex, std::try_to_lock);
1199 return !l.owns_lock();
1204 QFileInfo from(fileName);
1207 QFile::remove(to.canonicalFilePath());
1209 return QFile::copy(fileName, to.absoluteFilePath());
1215 qreal scale = qreal(size)/qreal(qMax(geometry().width(), geometry().height()));
1216 QImage
layoutThumbnail = QImage(qRound(geometry().width()*scale), qRound(geometry().height()*scale), QImage::Format_ARGB32);
1220 Q_FOREACH(
const QObject *child, children()) {
1221 if (child->isWidgetType()) {
1222 const QWidget *w =
static_cast<const QWidget *
>(child);
1224 if (w->isVisible() && !w->property(
"_kis_excludeFromLayoutThumbnail").toBool()) {
1225 QRect wRect = QRectF(w->geometry().x()*scale
1226 , w->geometry().y()*scale
1227 , w->geometry().width()*scale
1228 , w->geometry().height()*scale
1231 wRect = wRect.intersected(
layoutThumbnail.rect().adjusted(-1, -1, -1, -1));
1233 gc.setBrush(this->
palette().window());
1234 if (w ==
d->widgetStack) {
1235 gc.setBrush(
d->mdiArea->background());
1237 gc.setPen(this->
palette().windowText().color());
1259 std::unique_lock<QMutex> l(
d->savingEntryMutex, std::try_to_lock);
1260 if (!l.owns_lock())
return false;
1270 QMessageBox::critical(qApp->activeWindow(),
1271 i18nc(
"@title:window",
"Krita"),
1272 i18n(
"You are saving a file while the image is "
1273 "still rendering. The saved file may be "
1274 "incomplete or corrupted.\n\n"
1275 "Please select a location where the original "
1276 "file will not be overridden!"));
1282 if (document->isRecovered()) {
1286 if (document->path().isEmpty()) {
1293 QByteArray nativeFormat = document->nativeFormatMimeType();
1294 QByteArray oldMimeFormat = document->mimeType();
1296 QUrl suggestedURL = QUrl::fromLocalFile(document->path());
1301 if (!mimeFilter.contains(oldMimeFormat)) {
1302 dbgUI <<
"KisMainWindow::saveDocument no export filter for" << oldMimeFormat;
1308 QString suggestedFilename = QFileInfo(suggestedURL.toLocalFile()).completeBaseName();
1310 if (!suggestedFilename.isEmpty()) {
1312 suggestedURL = suggestedURL.adjusted(QUrl::RemoveFilename);
1313 suggestedURL.setPath(suggestedURL.path() + suggestedFilename);
1322 if (document->path().isEmpty() || isExporting || saveas) {
1325 bool justChangingFilterOptions =
false;
1328 dialog.setCaption(isExporting ? i18n(
"Exporting") : i18n(
"Saving As"));
1332 if (isExporting && !
d->lastExportLocation.isEmpty() && !
d->lastExportLocation.contains(QDir::tempPath())) {
1335 QString proposedPath = QFileInfo(
d->lastExportLocation).absolutePath();
1337 QString proposedFileName = suggestedURL.isEmpty() ? document->documentInfo()->aboutInfo(
"title") : QFileInfo(suggestedURL.toLocalFile()).completeBaseName();
1339 QString proposedMimeType =
d->lastExportedFormat.isEmpty() ?
"" :
d->lastExportedFormat;
1343 dialog.setDefaultDir(proposedPath +
"/" + proposedFileName +
"." + proposedExtension,
true);
1344 dialog.setMimeTypeFilters(mimeFilter, proposedMimeType);
1349 QByteArray default_mime_type = cfg.
exportMimeType(
false).toUtf8();
1350 QString proposedMimeType = QString::fromLatin1(default_mime_type);
1353 KConfigGroup group = KSharedConfig::openConfig()->group(
"File Dialogs");
1354 QString proposedPath = group.readEntry(
"SaveAs",
"");
1356 if (proposedPath.isEmpty()) {
1357 proposedPath = group.readEntry(
"OpenDocument",
"");
1360 if (proposedPath.isEmpty()) {
1361 proposedPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
1367 if(default_mime_type ==
"all/mime"){
1368 dialog.setDefaultDir(suggestedURL.isEmpty() ? proposedPath : proposedPath +
"/" + QFileInfo(suggestedURL.toLocalFile()).completeBaseName(),
true);
1371 if (default_mime_type !=
"all/mime" && !default_mime_type.isEmpty()) {
1374 dialog.setDefaultDir(suggestedURL.isEmpty() ? proposedPath : proposedPath +
"/" + QFileInfo(suggestedURL.toLocalFile()).completeBaseName() +
"." + proposedExtension,
true);
1379 dialog.setDefaultDir(suggestedURL.isEmpty() ? proposedPath : suggestedURL.toLocalFile(),
true);
1380 default_mime_type = document->mimeType().isEmpty() ? nativeFormat : document->mimeType();
1382 dialog.setMimeTypeFilters(mimeFilter, QString::fromLatin1(default_mime_type));
1385 QString newFilePath = dialog.filename();
1388 if (newFilePath.isEmpty()) {
1393 if (document->documentInfo()->aboutInfo(
"title") == i18n(
"Unnamed")) {
1394 QString fn = newFilePath;
1396 document->documentInfo()->setAboutInfo(
"title", info.completeBaseName());
1399 QByteArray outputFormat = nativeFormat;
1402 outputFormat = outputFormatString.toLatin1();
1406 justChangingFilterOptions = (newFilePath == document->path()) && (outputFormat == document->mimeType());
1409 QString path = QFileInfo(
d->lastExportLocation).absolutePath();
1410 QString filename = QFileInfo(document->path()).completeBaseName();
1411 justChangingFilterOptions = (QFileInfo(newFilePath).absolutePath() == path)
1412 && (QFileInfo(newFilePath).completeBaseName() == filename)
1413 && (outputFormat ==
d->lastExportedFormat);
1416 bool wantToSave =
true;
1419 if (!justChangingFilterOptions) {
1420 if (!document->isNativeFormat(outputFormat))
1426 ret = document->saveAs(newFilePath, outputFormat,
true);
1428 dbgUI <<
"Successful Save As!";
1431 dbgUI <<
"Failed Save As!";
1436 ret = document->exportDocument(newFilePath, outputFormat, isAdvancedExporting,
true);
1438 d->lastExportLocation = newFilePath;
1439 d->lastExportedFormat = outputFormat;
1455 if (document->isModified()) {
1456 ret = document->save(
true, 0);
1460 dbgUI <<
"Failed Save!";
1470 activeView()->document()->undoStack()->undo();
1477 activeView()->document()->undoStack()->redo();
1484 e->setAccepted(
false);
1489 QAction *
action=
d->viewManager->actionCollection()->action(
"view_show_canvas_only");
1491 action->setChecked(
false);
1498 if (!closeAllowed) {
1499 e->setAccepted(
false);
1505 d->mdiArea->closeAllSubWindows();
1509 if (childrenList.isEmpty()) {
1512 d->deferredClosingEvent = e;
1513 d->canvasWindow->close();
1515 e->setAccepted(
false);
1521 KSharedConfigPtr config = KSharedConfig::openConfig();
1523 if (
d->windowSizeDirty ) {
1524 dbgUI <<
"KisMainWindow::saveWindowSettings";
1525 KConfigGroup group =
d->windowStateConfig;
1526 KWindowConfig::saveWindowSize(windowHandle(), group);
1528 d->windowSizeDirty =
false;
1531 if (!
d->activeView ||
d->activeView->document()) {
1534 KConfigGroup group =
d->windowStateConfig;
1538 for (QMap<QString, QDockWidget*>::const_iterator i =
d->dockWidgetsMap.constBegin();
1539 i !=
d->dockWidgetsMap.constEnd(); ++i) {
1540 if (i.value()->widget()) {
1541 KConfigGroup dockGroup = group.group(QString(
"DockWidget ") + i.key());
1542 dockGroup.writeEntry(
"Locked", i.value()->property(
"Locked").toBool());
1543 dockGroup.writeEntry(
"DockArea", (
int) dockWidgetArea(i.value()));
1544 dockGroup.writeEntry(
"xPosition", (
int) i.value()->widget()->x());
1545 dockGroup.writeEntry(
"yPosition", (
int) i.value()->widget()->y());
1547 dockGroup.writeEntry(
"width", (
int) i.value()->widget()->width());
1548 dockGroup.writeEntry(
"height", (
int) i.value()->widget()->height());
1554 KSharedConfig::openConfig()->sync();
1561 d->windowSizeDirty =
true;
1562 KXmlGuiWindow::resizeEvent(e);
1580 QAction *
action=
d->viewManager->actionCollection()->action(
"view_show_canvas_only");
1588 if (!
event->spontaneous()) {
1592 Q_EMIT sigFullscreenOnShow(
true);
1594 return KXmlGuiWindow::showEvent(
event);
1600 if (widgetIndex == 0) {
1601 if (widgetIndexChanged) {
1607 if (
d->mdiArea->subWindowList().isEmpty()) {
1621 statusBar()->setVisible(
KisConfig(
true).showStatusBar());
1626 for (QAction *
action : actions) {
1628 action->setEnabled(widgetIndex);
1641 statusBar()->hide();
1644 for (QToolBar *toolbar : toolbars) {
1645 if (toolbar->objectName() !=
"mainToolBar") {
1653 d->activeView = view;
1655 if (
d->undoActionsUpdateManager) {
1656 d->undoActionsUpdateManager->setCurrentDocument(view ? view->
document() : 0);
1659 d->viewManager->setCurrentView(view);
1661 d->activeViewConnections.clear();
1662 d->activeViewConnections.addConnection(view->
document(),
1663 SIGNAL(sigPathChanged(QString)),
1666 d->activeViewConnections.addConnection(view->
document(),
1667 SIGNAL(sigReadWriteChanged(
bool)),
1678 d->activeViewConnections.clear();
1685 QTabBar *tabBar =
d->findTabBarHACK();
1687 if (!tabBar &&
d->mdiArea->viewMode() == QMdiArea::TabbedView) {
1688 qWarning() <<
"WARNING!!! Cannot find QTabBar in the main window! Looks like Qt has changed behavior. Drag & Drop between multiple tabs might not work properly (tabs will not switch automatically)!";
1691 if (tabBar && tabBar->isVisible()) {
1692 QPoint pos = tabBar->mapFromGlobal(mapToGlobal(
event->pos()));
1693 if (tabBar->rect().contains(pos)) {
1694 const int tabIndex = tabBar->tabAt(pos);
1696 if (tabIndex >= 0 && tabBar->currentIndex() != tabIndex) {
1697 d->tabSwitchCompressor->start(tabIndex);
1699 }
else if (
d->tabSwitchCompressor->isActive()) {
1700 d->tabSwitchCompressor->stop();
1707 if (
d->tabSwitchCompressor->isActive()) {
1708 d->tabSwitchCompressor->stop();
1715 QTabBar *tabBar =
d->findTabBarHACK();
1716 if (!tabBar)
return;
1718 tabBar->setCurrentIndex(index);
1723 const int currentIndex = show ? 0 : 1;
1724 if (
d->widgetStack->currentIndex() != currentIndex) {
1725 setUpdatesEnabled(
false);
1730 d->widgetStack->setCurrentIndex(currentIndex);
1732 d->widgetStack->setCurrentIndex(currentIndex);
1735 setUpdatesEnabled(
true);
1744 startupWidget->setWindowModality(Qt::WindowModal);
1745 startupWidget->setWindowTitle(i18n(
"Create new document"));
1768 item.
icon =
"document-new";
1769 item.
title = i18n(
"Custom Document");
1781 item.
title = i18n(
"Create from Clipboard");
1782 item.
icon =
"tab-new";
1789 startupWidget->exec();
1790 startupWidget->deleteLater();
1795 dbgUI <<
"slotImportFile()";
1807 Q_FOREACH (
const QString& url, urls) {
1809 if (!url.isEmpty()) {
1810 OpenFlags flags = isImporting ?
Import :
None;
1813 warnKrita <<
"Loading" << url <<
"failed";
1826 if (
saveDocument(
d->activeView->document(),
false,
false,
false)) {
1833 if (
saveDocument(
d->activeView->document(),
true,
false,
false)) {
1840 if (
saveDocument(
d->activeView->document(),
true,
true,
false)) {
1846 if (
saveDocument(
d->activeView->document(),
true,
true,
true)) {
1857 return d->viewManager->canvasResourceProvider()->resourceManager();
1862 return d->mdiArea->subWindowList().size();
1867 return d->windowStateConfig;
1873 if (
d->widgetStack->currentIndex() == 0) {
1878 if (restoreNormalState) {
1879 QAction *showCanvasOnly =
d->viewManager->actionCollection()->action(
"view_show_canvas_only");
1881 if (showCanvasOnly && showCanvasOnly->isChecked()) {
1882 showCanvasOnly->setChecked(
false);
1885 d->windowStateConfig.writeEntry(
"ko_geometry", saveGeometry().toBase64());
1886 d->windowStateConfig.writeEntry(
"State", saveState().toBase64());
1889 if (!
d->toggleDockers->isChecked()) {
1890 restoreState(
d->dockerStateBeforeHiding);
1893 statusBar()->setVisible(
true);
1894 menuBar()->setVisible(
true);
1906 QByteArray oldState = saveState();
1912 dock->setProperty(
"Locked",
false);
1913 dock->toggleViewAction()->setEnabled(
true);
1915 if (dock->titleBarWidget() && !dock->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
1916 dock->titleBarWidget()->setVisible(showTitlebars);
1921 bool success = KXmlGuiWindow::restoreState(state);
1924 KXmlGuiWindow::restoreState(oldState);
1926 if (dock->titleBarWidget() && !dock->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
1927 dock->titleBarWidget()->setVisible(showTitlebars || dock->isFloating());
1937 QString md5 = sender()->property(
"md5").toString();
1944 qWarning() <<
"Could not retrieve resource for" << md5;
1953 int actionsCount = 0;
1958 if (
auto collection = c->actionCollection()) {
1959 actionCollections.append(collection);
1960 actionsCount += collection->count();
1969 actionCollections.append(layerActionCollection);
1970 actionsCount += layerActionCollection->
count();
1973 d->commandBar->updateBar(actionCollections, actionsCount);
1979 d->commandBar->activateWindow();
1992 warning = i18n(
"You don't have any resource bundles enabled.");
1996 warning += i18n(
"\nThere are no brush presets available. Please enable a bundle that has presets before continuing.\n");
1997 QMessageBox::critical(
this, i18nc(
"@title:window",
"Krita"), warning);
2006 QMessageBox::warning(
this, i18nc(
"@title:window",
"Krita"), warning + i18n(
"\nOnly your local resources are available."));
2019 if (dock->titleBarWidget() && !dock->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
2020 dock->titleBarWidget()->setVisible(showTitlebars || dock->isFloating());
2025 activeKisView()->resourceProvider()->notifyLoadingWorkspace(workspace);
2028 d->viewManager->notifyWorkspaceLoaded();
2035 QByteArray currentWorkspace = saveState();
2037 if (!
d->workspaceBorrowedBy.isNull()) {
2038 if (other->
id() ==
d->workspaceBorrowedBy) {
2040 d->workspaceBorrowedBy = QUuid();
2041 return currentWorkspace;
2049 d->workspaceBorrowedBy = other->
id();
2050 return originalLayout;
2055 d->workspaceBorrowedBy = other->
id();
2056 return currentWorkspace;
2062 QByteArray workspaceB = b->borrowWorkspace(a);
2065 b->restoreWorkspaceState(workspaceA);
2070 return d->viewManager;
2075 if (!
d->activeView->document())
2083 KoDocumentInfoDlg *dlg =
d->activeView->document()->createDocumentInfoDialog(
this, docInfo);
2087 d->activeView->document()->setModified(
false);
2089 d->activeView->document()->setModified(
true);
2098 Q_FOREACH (QMdiSubWindow *subwin,
d->mdiArea->subWindowList()) {
2100 if(!subwin->close())
2124 if (!document)
return;
2128 if (dlg.exec() == QDialog::Accepted) {
2130 int firstFrame = dlg.firstFrame();
2131 int step = dlg.step();
2132 bool startFrom1 = dlg.startFrom1();
2133 bool autoAddHoldframes = dlg.autoAddHoldframes();
2139 int isAscending = dlg.isAscending();
2140 KisImportExportErrorCode status = importer.import(files, firstFrame, step, autoAddHoldframes, startFrom1, isAscending);
2145 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"Could not finish import animation:\n%1", msg));
2147 activeView()->canvasBase()->refetchDataFromImage();
2156 if (dlg.exec() == QDialog::Accepted) {
2157 const QTemporaryDir outputLocation(QDir::tempPath() + QDir::separator() +
"krita" + QDir::separator() +
"import_files");
2158 RenderedFrames renderedFrames = dlg.renderFrames(QDir(outputLocation.path()));
2159 dbgFile <<
"Frames rendered to directory: " << outputLocation.path();
2160 QStringList documentInfoList = dlg.documentInfo();
2162 if (renderedFrames.
isEmpty())
return;
2164 dbgFile <<
"Animation Import options: " << documentInfoList;
2167 const int step = documentInfoList[0].toInt();
2168 const int fps = documentInfoList[1].toInt();
2170 const QString
name = QFileInfo(documentInfoList[3]).fileName();
2171 const bool useCurrentDocument = documentInfoList[4].toInt();
2172 bool useDocumentColorSpace =
false;
2174 if ( useCurrentDocument ) {
2177 dbgFile <<
"Current frames:" << document->image()->animationInterface()->totalLength() <<
"total frames:" << totalFrames;
2178 if ( document->image()->animationInterface()->totalLength() < totalFrames ) {
2179 document->image()->animationInterface()->setDocumentRangeStartFrame(0);
2180 document->image()->animationInterface()->setDocumentRangeEndFrame(totalFrames);
2183 const int width = documentInfoList[5].toInt();
2184 const int height = documentInfoList[6].toInt();
2185 const double resolution = documentInfoList[7].toDouble();
2187 const QString colorModel = documentInfoList[8];
2188 const QString colorDepth = documentInfoList[9];
2189 const QString profile = documentInfoList[10];
2190 useDocumentColorSpace = profile !=
"Default";
2193 document->setObjectName(name);
2199 QColor qc(Qt::white);
2203 if (!document->newImage(name, width, height, cs, bgColor,
KisConfig::RASTER_LAYER, 1,
"",
double(resolution / 72) )) {
2204 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"Failed to create new document. Animation import aborted."));
2208 document->image()->animationInterface()->setFramerate(fps);
2209 document->image()->animationInterface()->setDocumentRangeStartFrame(0);
2210 document->image()->animationInterface()->setDocumentRangeEndFrame(totalFrames);
2223 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"Could not finish import animation:\n%1", msg));
2226 activeView()->canvasBase()->refetchDataFromImage();
2227 document->image()->refreshGraphAsync();
2228 document->image()->waitForDone();
2245 dlgAnimationRenderer.setCaption(i18n(
"Render Animation"));
2246 if (dlgAnimationRenderer.exec() == QDialog::Accepted) {
2323 if (
d->activeView &&
d->activeView->document()) {
2327 warnUI <<
"slotToolbarToggled : Toolbar " << sender()->objectName() <<
" not found!";
2336 setWindowState(windowState() | Qt::WindowFullScreen);
2338 setWindowState(windowState() & ~Qt::WindowFullScreen);
2340 d->fullScreenMode->setChecked(isFullScreen());
2348 if (!
d->dockWidgetsMap.contains(
factory->id())) {
2370 if (
dockWidget->titleBarWidget() && !
dockWidget->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
2376 if (!showTitlebars) {
2377 if (
dockWidget->titleBarWidget() && !
dockWidget->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
2378 dockWidget->titleBarWidget()->setVisible(
false);
2380 dockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures);
2383 dockWidget->widget()->layout()->setContentsMargins(1, 1, 1, 1);
2385 Qt::DockWidgetArea side = Qt::RightDockWidgetArea;
2386 bool visible =
true;
2388 switch (
factory->defaultDockPosition()) {
2393 side = Qt::TopDockWidgetArea;
break;
2395 side = Qt::LeftDockWidgetArea;
break;
2397 side = Qt::BottomDockWidgetArea;
break;
2399 side = Qt::RightDockWidgetArea;
break;
2402 side = Qt::RightDockWidgetArea;
2406 KConfigGroup group =
d->windowStateConfig.group(
"DockWidget " +
factory->id());
2407 side =
static_cast<Qt::DockWidgetArea
>(group.readEntry(
"DockArea",
static_cast<int>(side)));
2408 if (side == Qt::NoDockWidgetArea) side = Qt::RightDockWidgetArea;
2415 bool locked = group.readEntry(
"Locked",
false);
2416 if (titleBar && locked) {
2419 else if (
dockWidget->titleBarWidget()->inherits(
"KisUtilityTitleBar") && locked){
2431 dockWidget->setAttribute(Qt::WA_MacSmallSize,
true);
2442 Q_FOREACH (QObject *child, children()) {
2443 if (child->inherits(
"QTabBar")) {
2454 Q_FOREACH (
auto key,
d->actionMap.keys()) {
2455 if(
d->actionMap.value(key)->isChecked()) {
2458 qApp->setStyle(key);
2462#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
2463 if (qApp->style()->objectName() ==
"macintosh") {
2464 d->themeManager->setCurrentTheme(
"System");
2467 if (qApp->style()->name() ==
"macos") {
2468 d->themeManager->setCurrentTheme(
"System");
2478 return d->dockWidgetsMap.values();
2483 if (!
d->dockWidgetsMap.contains(
id))
return 0;
2484 return d->dockWidgetsMap[
id];
2496 observers << observer;
2499 warnKrita << docker <<
"is not a canvas observer";
2510 d->dockerStateBeforeHiding = saveState();
2512 Q_FOREACH (QObject*
widget, children()) {
2513 if (
widget->inherits(
"QDockWidget")) {
2514 QDockWidget* dw =
static_cast<QDockWidget*
>(
widget);
2515 if (dw->isVisible() && !(onWelcomePage && dw->property(
"ShowOnWelcomePage").toBool())) {
2522 restoreState(
d->dockerStateBeforeHiding);
2530 d->mdiCascade->setEnabled(enabled);
2531 d->mdiNextWindow->setEnabled(enabled);
2532 d->mdiPreviousWindow->setEnabled(enabled);
2533 d->mdiTile->setEnabled(enabled);
2534 d->close->setEnabled(enabled);
2535 d->closeAll->setEnabled(enabled);
2548 QMdiSubWindow *subWindow =
d->mdiArea->currentSubWindow();
2550 QMenu *menu = subWindow->systemMenu();
2551 if (menu && menu->actions().size() == 8) {
2552 Q_FOREACH (QAction *
action, menu->actions()) {
2553 action->setShortcut(QKeySequence());
2556 menu->actions().last()->deleteLater();
2560 d->actionManager()->updateGUI();
2577 if (primary.isNull())
return;
2579 if (
d->id == primary) {
2580 if (!
d->workspaceBorrowedBy.isNull()) {
2582 if (!borrower)
return;
2586 if (
d->workspaceBorrowedBy == primary)
return;
2589 if (!primaryWindow)
return;
2597 QMenu *menu =
d->windowMenu->menu();
2601 menu->addAction(
d->newWindow);
2603 menu->addAction(
d->documentMenu);
2605 QMenu *docMenu =
d->documentMenu->menu();
2608 QFontMetrics fontMetrics = docMenu->fontMetrics();
2609 QRect geom = this->geometry();
2610 QPoint
p(geom.width() / 2 + geom.left(), geom.height() / 2 + geom.top());
2611 QScreen *screen = qApp->screenAt(
p);
2612 int fileStringWidth = 300;
2614 fileStringWidth = int(screen->availableGeometry().width() * .40f);
2618 QString title = fontMetrics.elidedText(doc->path(), Qt::ElideMiddle, fileStringWidth);
2619 if (title.isEmpty() && doc->image()) {
2620 title = doc->image()->objectName();
2622 QAction *
action = docMenu->addAction(title);
2623 action->setIcon(qApp->windowIcon());
2624 connect(
action, SIGNAL(triggered()),
d->documentMapper, SLOT(map()));
2625 d->documentMapper->setMapping(
action, doc);
2629 menu->addAction(
d->workspaceMenu);
2636 while (resourceIterator.
hasNext()) {
2639 action->setProperty(
"md5", QVariant::fromValue<QString>(resource->md5sum()));
2644 &QAction::triggered,
2651 dialog.setMimeTypeFilters(mimeTypes);
2652 dialog.setCaption(i18nc(
"@title:window",
"Choose File to Add"));
2653 QString filename = dialog.filename();
2659 &QAction::triggered,
2662 name = QInputDialog::getText(
this, i18nc(
"@title:window",
"New Workspace..."),
2663 i18nc(
"@label:textbox",
"Name:"));
2664 if (name.isEmpty()) {
2669 workspace->setDockerState(m_this->saveState());
2671 workspace->setValid(
true);
2675 d->viewManager->canvasResourceProvider()->notifySavingWorkspace(workspace);
2676 workspace->setValid(
true);
2678 workspace->setFilename(name.replace(
" ",
"_") + workspace->defaultFileExtension());
2679 workspace->setName(name);
2687 menu->addSeparator();
2688 menu->addAction(
d->close);
2689 menu->addAction(
d->closeAll);
2690 if (
d->mdiArea->viewMode() == QMdiArea::SubWindowView) {
2691 menu->addSeparator();
2692 menu->addAction(
d->mdiTile);
2693 menu->addAction(
d->mdiCascade);
2695 menu->addSeparator();
2696 menu->addAction(
d->mdiNextWindow);
2697 menu->addAction(
d->mdiPreviousWindow);
2698 menu->addSeparator();
2701 for (
int i = 0; i < windows.size(); ++i) {
2703 if (child && child->document()) {
2706 text = i18n(
"&%1 %2", i + 1, fontMetrics.elidedText(child->document()->path(), Qt::ElideMiddle, fileStringWidth));
2709 text = i18n(
"%1 %2", i + 1, fontMetrics.elidedText(child->document()->path(), Qt::ElideMiddle, fileStringWidth));
2712 QAction *
action = menu->addAction(text);
2713 action->setIcon(qApp->windowIcon());
2714 action->setCheckable(
true);
2716 connect(
action, SIGNAL(triggered()),
d->windowMapper, SLOT(map()));
2717 d->windowMapper->setMapping(
action, windows.at(i));
2721 bool showMdiArea = windows.count( ) > 0;
2727 Q_FOREACH (QObject*
widget, children()) {
2728 if (
widget->inherits(
"QDockWidget")) {
2729 QDockWidget* dw =
static_cast<QDockWidget*
>(
widget);
2731 if ( dw->objectName() ==
"ToolBox") {
2732 dw->setEnabled(showMdiArea);
2740 bool onlyOne =
false;
2741 if (
d->mdiArea->subWindowList().size() == 1 &&
d->mdiArea->viewMode() == QMdiArea::SubWindowView) {
2744 Q_FOREACH (QMdiSubWindow *subwin,
d->mdiArea->subWindowList()) {
2746 subwin->setWindowFlags(subwin->windowFlags() | Qt::FramelessWindowHint);
2747 subwin->showMaximized();
2749 subwin->setWindowFlags((subwin->windowFlags() | Qt::FramelessWindowHint) ^ Qt::FramelessWindowHint);
2760 QMdiSubWindow *subwin = qobject_cast<QMdiSubWindow *>(window);
2763 if (subwin && subwin !=
d->activeSubWindow) {
2764 KisView *view = qobject_cast<KisView *>(subwin->widget());
2769 d->activeSubWindow = subwin;
2772 d->actionManager()->updateGUI();
2778 QMdiArea::ViewMode viewMode = (QMdiArea::ViewMode)cfg.
readEntry<
int>(
"mdi_viewmode", (
int)QMdiArea::TabbedView);
2779 d->mdiArea->setViewMode(viewMode);
2780 Q_FOREACH (QMdiSubWindow *subwin,
d->mdiArea->subWindowList()) {
2781 subwin->setOption(QMdiSubWindow::RubberBandMove, cfg.
readEntry<
int>(
"mdi_rubberband", cfg.
useOpenGL()));
2782 subwin->setOption(QMdiSubWindow::RubberBandResize, cfg.
readEntry<
int>(
"mdi_rubberband", cfg.
useOpenGL()));
2783 if (viewMode == QMdiArea::TabbedView) {
2784 subwin->setWindowState(Qt::WindowMaximized);
2794 if (viewMode == QMdiArea::TabbedView) {
2795 Qt::WindowFlags oldFlags = subwin->windowFlags();
2796 Qt::WindowFlags flags = oldFlags;
2798 flags &= ~Qt::WindowStaysOnTopHint;
2799 flags &= ~Qt::WindowStaysOnBottomHint;
2801 if (flags != oldFlags) {
2802 subwin->setWindowFlags(flags);
2803 subwin->showMaximized();
2811 KConfigGroup group( KSharedConfig::openConfig(),
"theme");
2813 d->themeManager->setCurrentTheme(group.readEntry(
"Theme",
"Krita dark"));
2815 d->actionManager()->updateGUI();
2820 d->mdiArea->setBackground(brush);
2823 if (backgroundImage !=
"") {
2824 QImage image(backgroundImage);
2825 QBrush brush(image);
2826 d->mdiArea->setBackground(brush);
2829 d->mdiArea->update();
2833 Q_FOREACH (QObject*
widget, children()) {
2834 if (
widget->inherits(
"QDockWidget")) {
2835 QDockWidget* dw =
static_cast<QDockWidget*
>(
widget);
2843 KisDocument *doc = qobject_cast<KisDocument*>(document);
2845 d->actionManager()->updateGUI();
2855 QMessageBox::warning(
this, i18nc(
"@title:window",
"Krita"),
2856 "Creating a New Main Window is unsupported on Android");
2867 if (
d->mdiArea->currentSubWindow()) {
2868 d->mdiArea->currentSubWindow()->close();
2869 d->actionManager()->updateGUI();
2878 m_errorMessage = i18n(
"The Krita LittleCMS color management plugin is not installed. Krita will quit now.");
2894 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Installation error"),
m_errorMessage);
2908 if (!
d->mdiArea)
return 0;
2918 bool isOurOwnView =
false;
2921 if (view && view->canvasController() == controller) {
2922 isOurOwnView = view->mainWindow() ==
this;
2926 if (!isOurOwnView)
return;
2928 Q_FOREACH (QWidget *w, optionWidgetList) {
2930 w->setAttribute(Qt::WA_MacSmallSize,
true);
2935 if (
d->toolOptionsDocker) {
2936 d->toolOptionsDocker->setOptionWidgets(optionWidgetList);
2939 d->viewManager->paintOpBox()->newOptionWidgets(optionWidgetList);
2970 d->undoActionsUpdateManager->setCurrentDocument(
d->activeView ?
d->activeView->document() : 0);
3004 d->themeManager->setThemeMenuAction(
new KActionMenu(i18nc(
"@action:inmenu",
"&Themes"),
this));
3007 connect(
this, SIGNAL(
themeChanged()),
d->welcomePage, SLOT(slotUpdateThemeColors()), Qt::UniqueConnection);
3013 d->toggleDockers->setChecked(
true);
3021 d->toggleDetachCanvas->setChecked(
false);
3036 connect(
d->mdiCascade, SIGNAL(triggered()),
d->mdiArea, SLOT(cascadeSubWindows()));
3039 connect(
d->mdiTile, SIGNAL(triggered()),
d->mdiArea, SLOT(tileSubWindows()));
3042 connect(
d->mdiNextWindow, SIGNAL(triggered()),
d->mdiArea, SLOT(activateNextSubWindow()));
3045 connect(
d->mdiPreviousWindow, SIGNAL(triggered()),
d->mdiArea, SLOT(activatePreviousSubWindow()));
3062 for (
int i = 0; i < 2; i++) {
3063 d->expandingSpacers[i] =
new KisAction(i18n(
"Expanding Spacer"));
3064 d->expandingSpacers[i]->setDefaultWidget(
new QWidget(
this));
3065 d->expandingSpacers[i]->defaultWidget()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
3080 toolBar->layout()->setSpacing(4);
3081 toolBar->setStyleSheet(
"QToolBar { border: none }");
3084 Q_FOREACH (QAction *ac,
toolBar->actions()){
3085 if (ac->icon().pixmap(QSize(1,1)).isNull() ==
false){
3086 ac->setPriority(QAction::LowPriority);
3088 ac->setIcon(QIcon());
3098 KConfigGroup cfg =
d->windowStateConfig;
3099 QByteArray geom = QByteArray::fromBase64(cfg.readEntry(
"ko_geometry", QByteArray()));
3100 if (!restoreGeometry(geom)) {
3101 QRect desk = this->screen()->availableGeometry();
3103 quint32 x = desk.x();
3104 quint32 y = desk.y();
3109 const int deskWidth = desk.width();
3110 if (deskWidth > 1024) {
3113 w = (deskWidth / 3) * 2;
3114 h = (desk.height() / 3) * 2;
3121 x += (desk.width() - w) / 2;
3122 y += (desk.height() - h) / 2;
3125 setGeometry(geometry().x(), geometry().y(), w, h);
3127 d->fullScreenMode->setChecked(isFullScreen());
3132 QDesktopServices::openUrl(QUrl(
"https://docs.krita.org"));
3138 if (dock->titleBarWidget() && !dock->titleBarWidget()->inherits(
"KisUtilityTitleBar")) {
3139 dock->titleBarWidget()->setVisible(show || dock->isFloating());
3156 QScreen *screen = QGuiApplication::primaryScreen();
3158 for (QWindow* window: QGuiApplication::topLevelWindows()) {
3160 if ((window->type() == Qt::Popup)
3161 && (window->flags() & Qt::FramelessWindowHint) == 0
3162 && (window->geometry().topLeft() != QPoint(0, 0))) {
3165 int screenHeight = screen->geometry().width();
3166 int screenWidth = screen->geometry().height();
3169 int new_x = (window->position().x() * screenWidth) / screenHeight;
3170 int new_y = (window->position().y() * screenHeight) / screenWidth;
3173 int winWidth = window->geometry().width();
3174 int winHeight = window->geometry().height();
3177 if (new_x > screenWidth - winWidth) {
3178 new_x = screenWidth - winWidth;
3182 if (new_y > screenHeight - winHeight) {
3183 new_y = screenHeight - winHeight;
3188 window->setPosition(QPoint(new_x, new_y));
3201 return (proxy.rowCount() > 0);
3219 QFile file(xmlPath);
3220 if (!file.exists()) {
3225 if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file)) {
3229 QDomNodeList overridesList = doc.elementsByTagName(QStringLiteral(
"ActionIconOverrides"));
3230 if (!overridesList.isEmpty()) {
3231 QDomElement overridesElement = overridesList.at(0).toElement();
3232 QDomNodeList actions = overridesElement.elementsByTagName(QStringLiteral(
"Action"));
3233 for (
int i = 0; i < actions.count(); ++i) {
3234 QDomElement actionElement = actions.at(i).toElement();
3235 QString name = actionElement.attribute(QStringLiteral(
"name"));
3236 QString icon = actionElement.attribute(QStringLiteral(
"icon"));
3237 if (!name.isEmpty() && !icon.isEmpty()) {
3247#include <moc_KisMainWindow.cpp>
QList< QString > QStringList
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KDE top level main window with predefined action layout
QAction * toolBarMenuAction()
void setStandardToolBarMenuEnabled(bool enable)
void applyMainWindowSettings(const KConfigGroup &config) override
bool event(QEvent *event) override
virtual KisKXMLGUIFactory * guiFactory()
bool isHelpMenuEnabled() const
A KisActionManager class keeps track of KisActions. These actions are always associated with the GUI....
KisAction * createAction(const QString &name)
void addAction(const QString &name, KisAction *action)
KisAction * createStandardAction(KStandardAction::StandardAction, const QObject *receiver, const char *member)
@ ACTIVE_IMAGE
Activate if there is at least one image.
@ IMAGE_IS_WRITABLE
Activate KisDocument::isReadWrite() is active.
@ IMAGE_HAS_ANIMATION
Activate if the image has an animation.
void fromProperties(KisPropertiesConfigurationSP config)
Base class for the Krita app.
void setFavoriteResourceManager(KisFavoriteResourceManager *favoriteResourceManager)
static KisConfigNotifier * instance()
void notifyPixelGridModeChanged()
void notifyConfigChanged(void)
QString widgetStyle(bool defaultValue=false)
qint32 defImageHeight(bool defaultValue=false) const
void setFullscreenMode(const bool value) const
qint32 defImageWidth(bool defaultValue=false) const
void setWidgetStyle(QString name)
void writeEntry(const QString &name, const T &value)
QString getMDIBackgroundColor(bool defaultValue=false) const
QString getMDIBackgroundImage(bool defaultValue=false) const
bool showDockerTitleBars(bool defaultValue=false) const
qreal defImageResolution(bool defaultValue=false) const
QString exportMimeType(bool defaultValue) const
QString defColorProfile(bool defaultValue=false) const
void setShowDockerTitleBars(const bool value) const
bool toolOptionsInDocker(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
QString defColorModel(bool defaultValue=false) const
bool showDockers(bool defaultValue=false) const
bool useOpenGL(bool defaultValue=false) const
QString defaultColorDepth(bool defaultValue=false) const
void setFileBatchMode(const bool batchMode)
void setPath(const QString &path)
bool importDocument(const QString &path)
bool openPath(const QString &path, OpenFlags flags=None)
openPath Open a Path
bool hasAnimation() const
static KisImageConfigNotifier * instance()
void notifyConfigChanged(void)
KisGroupLayerSP rootLayer() const
KisImageAnimationInterface * animationInterface() const
QString errorMessage() const
bool isInternalError() const
static QStringList supportedMimeTypes(Direction direction)
A container for a set of QAction objects.
void setComponentDisplayName(const QString &displayName)
Q_INVOKABLE QAction * addAction(const QString &name, QAction *action)
QAction * action(int index) const
void addAssociatedWidget(QWidget *widget)
void setAutoSaveSettings(const QString &groupName=QLatin1String("MainWindow"), bool saveWindowSize=true)
void resetAutoSaveSettings()
void saveMainWindowSettings(KConfigGroup &config)
KisToolBar * toolBar(const QString &name=QString())
void closeEvent(QCloseEvent *) override
QList< KisToolBar * > toolBars() const
void setLocalXMLFile(const QString &file)
QAction * action(const char *name) const
KisKXMLGUIFactory * factory() const
void setXMLFile(const QString &file, bool merge=false, bool setXMLDoc=true)
void plugActionList(const QString &name, const QList< QAction * > &actionList)
virtual KisKActionCollection * actionCollection() const
void addClient(KisKXMLGUIClient *client)
QList< KisKXMLGUIClient * > clients() const
QMenu * createPopupMenu() override
KisActionManager * actionManager()
bool installBundle(const QString &fileName) const
Copy the given file into the bundle directory.
QPointer< KisView > activeKisView()
virtual void showAboutApplication()
showAboutApplication show the about box
QScopedPointer< KisUndoActionsUpdateManager > undoActionsUpdateManager
QDockWidget * dockWidget(const QString &id)
void applyActionIconOverridesFromLocalXML()
KisMainWindow(QUuid id=QUuid())
void closeCurrentWindow()
void setCanvasDetached(bool detached)
void guiLoadingFinished()
void dragLeaveEvent(QDragLeaveEvent *event) override
QImage layoutThumbnail()
layoutThumbnail
QTabBar * findTabBarHACK()
KisSignalAutoConnectionsStore activeViewConnections
QStringList showOpenFileDialog(bool isImporting)
void slotUpdateWidgetStyle()
bool checkPaintOpAvailable()
void dragMove(QDragMoveEvent *event)
void showWelcomeScreen(bool show)
void setActiveSubWindow(QWidget *window)
bool windowsLayoutSavingAllowed() const override
void slotLoadCanceled(const QString &)
void orientationChanged()
void slotConfigureToolbars()
QList< KoCanvasObserverBase * > canvasObservers() const override
void slotStoragesWarning(const QString &location=QString())
void slotNewToolbarConfig()
void themeChanged()
This signal is emitted when the color theme changes.
QMdiSubWindow * activeSubWindow
bool restoreWorkspaceState(const QByteArray &state)
KConfigGroup windowStateConfig
KisAction * renderAnimation
void updateSubwindowFlags()
void slotShowSessionManager()
QUuid workspaceBorrowedBy
void slotResetConfigurations()
void showErrorAndDie()
Quits Krita with error message from m_errorMessage.
QMap< QString, QAction * > actionMap
void slotUpdateReadWriteMode(bool readWrite)
bool checkActiveBundlesAvailable()
checkActiveStorages checks whether there is at least one bundle available and at least one paintop pr...
KisView * newView(QObject *document, QMdiSubWindow *subWindow=0)
bool openDocument(const QString &path, OpenFlags flags)
void toggleDockersVisibility(bool visible, bool onWelcomePage=false)
void showDocument(KisDocument *document)
void slotXmlGuiMakingChanges(bool finished)
void newOptionWidgets(KoCanvasController *controller, const QList< QPointer< QWidget > > &optionWidgetList)
KisView * addViewAndNotifyLoadingCompleted(KisDocument *document, QMdiSubWindow *subWindow=0)
QList< QDockWidget * > dockWidgets() const
Return the list of dock widgets belonging to this main window.
bool openDocumentInternal(const QString &path, KisMainWindow::OpenFlags f=KisMainWindow::OpenFlags())
QDockWidget * createDockWidget(KoDockFactoryBase *factory)
void resizeEvent(QResizeEvent *e) override
KisAction * renderAnimationAgain
virtual void showView(KisView *view, QMdiSubWindow *subWindow=0)
showView shows the given view, in subWindow if not null, in a new tab otherwise.
void addView(KisView *view, QMdiSubWindow *subWindow=0)
void setMainWindowLayoutForCurrentMainWidget(int widgetIndex, bool widgetIndexChanged)
QPointer< KisView > activeView
void slotUpdateSaveActionTitle(const QString &documentPath)
void slotPreferences()
slotPreferences open the preferences dialog
void slotFileOpenRecent(const QUrl &)
QString lastExportLocation
bool saveDocument(KisDocument *document, bool saveas, bool isExporting, bool isAdvancedExporting=false)
QByteArray lastExportedFormat
void showEvent(QShowEvent *event) override
KisViewManager * viewManager
bool hackIsSaving() const
void slotFileOpen(bool isImporting=false)
QMap< QString, QDockWidget * > dockWidgetsMap
void subWindowActivated()
void saveWindowState(bool restoreNormalState=false)
bool canvasDetached() const
KActionMenu * workspaceMenu
void viewFullscreen(bool fullScreen)
QList< QAction * > toolbarList
void restoringDone()
This signal is emitted right after the docker states have been successfully restored from config.
void activeViewChanged()
emitted when the current view has changed
KisCanvasWindow * canvasWindow
void initializeGeometry()
void notifyChildViewDestroyed(KisView *view)
void adjustLayoutForWelcomePage()
void setActiveView(KisView *view)
Set the active view, this will update the undo/redo actions.
void showDockerTitleBars(bool show)
static void swapWorkspaces(KisMainWindow *a, KisMainWindow *b)
KisAction * importAnimation
QByteArray dockerStateBeforeHiding
void removeRecentFile(QString url)
void slotSaveCanceled(const QString &)
KisAction * importVideoAnimation
Private(KisMainWindow *parent, QUuid id)
void switchTab(int index)
QByteArray borrowWorkspace(KisMainWindow *borrower)
void applyToolBarLayout()
void saveWindowSettings()
~KisMainWindow() override
QScopedPointer< KisSignalCompressorWithParam< int > > tabSwitchCompressor
void dragMoveEvent(QDragMoveEvent *event) override
void slotToolbarToggled(bool toggle)
void closeEvent(QCloseEvent *e) override
KoCanvasResourceProvider * resourceManager() const
The KisMainwindowObserver class is an interface for dock widgets that want to keep track of the main ...
virtual void setViewManager(KisViewManager *kisview)=0
static QStringList suffixesForMimeType(const QString &mimeType)
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
void addCustomDocumentWidget(QWidget *widget, const QString &title, const QString &untranslatedName, const QString &icon=QString())
bool closeSession(bool keepWindows=false)
void removeMainWindow(KisMainWindow *mainWindow)
KisView * createView(KisDocument *document, KisViewManager *viewManager, QWidget *parent)
static KisPart * instance()
void addDocument(KisDocument *document, bool notify=true)
void queueAddRecentURLToAllMainWindowsOnFileSaved(QUrl url, QUrl oldUrl=QUrl())
void sigMainWindowCreated()
KisMainWindow * windowById(QUuid id) const
KisDocument * createDocument() const
void showSessionManager()
void notifyMainWindowIsBeingCreated(KisMainWindow *mainWindow)
notifyMainWindowIsBeingCreated emits the sigMainWindowCreated signal
KisMainWindow * createMainWindow(QUuid id=QUuid())
static KisRecentDocumentsModelWrapper * instance()
void remove(const QUrl &url)
static KisRecentFilesManager * instance()
The KisResourceIterator class provides an iterator for a KisResourceModel.
const KisResourceItemSP next()
static KisResourceLoaderRegistry * instance()
QStringList mimeTypes(const QString &resourceType) const
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
static KisResourceServerProvider * instance()
KoResourceServer< KisWorkspaceResource > * workspaceServer()
KisPaintOpPresetResourceServer * paintOpPresetServer()
static QString storageTypeToUntranslatedString(StorageType storageType)
static KoResourceSP importResourceFileWithUserInput(QWidget *widgetParent, QString storageLocation, QString resourceType, QString resourceFilepath)
static bool addResourceWithUserInput(QWidget *widgetParent, KoResourceSP resource, QString storageLocation="")
The KisSignalMapper class bundles signals from identifiable senders.
@ ByStorageType
Pass a string list of storage types.
void setFilter(FilterType filterType, QVariant filter)
static KisStorageModel * instance()
static void log(const QString &message)
Logs with date/time.
A special utility titlebar with a title and controls, as well as a central area for adding frequently...
void setLocked(bool locked)
KisDocument * document() const
void setCurrentView(KisView *view)
KisInputManager * inputManager() const
Filters events and sends them to canvas actions.
QPointer< KoUpdater > createUnthreadedUpdater(const QString &name)
create a new progress updater
KisSelectionManager * selectionManager()
KisImageWSP image() const
Return the image this view is displaying.
KisCanvas2 * canvasBase() const
void slotThemeChanged(QPalette pal)
void setSubWindow(QMdiSubWindow *subWindow)
QPointer< KisDocument > document
void slotLoadingFinished()
void setViewManager(KisViewManager *view)
A widget for displaying if no documents are open. This will display in the MDI area.
QUuid primaryWindowId() const
bool primaryWorkspaceFollowsFocus() const
static KisWindowLayoutManager * instance()
void activeDocumentChanged(KisDocument *document)
Resource for storing of workspaces.
void setObservedCanvas(KoCanvasBase *canvas)
static KoColorSpaceEngineRegistry * instance()
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
void toQColor(QColor *c) const
a convenience method for the above.
@ DockRight
Right of the centra widget.
@ DockTop
Above the central widget.
@ DockBottom
Below the central widget.
@ DockMinimized
Not docked, but reachable via the menu.
@ DockLeft
Left of the centra widget.
@ DockTornOff
Floating as its own top level window.
static KoDockRegistry * instance()
The dialog that shows information about the document.
The class containing all meta information about a document.
const T value(const QString &id) const
void load(const QString &serviceType, const PluginsConfig &config=PluginsConfig(), QObject *owner=0, bool cache=true)
static KoPluginLoader * instance()
static QString locateLocal(const QString &type, const QString &filename, bool createDir=false)
static QString getAppDataLocation()
int resourceCount() const
QSharedPointer< T > resource(const QString &md5, const QString &fileName, const QString &name)
resource retrieves a resource. If the md5sum is not empty, the resource will only be retrieved if a r...
#define KIS_ASSERT_RECOVER_NOOP(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
constexpr const char * currentUnderlyingStyleNameProperty
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
KRecentFilesAction * openRecent(const QObject *recvr, const char *slot, QObject *parent)
const char * name(StandardAction id)
KRITAUI_EXPORT bool render(KisDocument *doc, KisViewManager *viewManager, KisAnimationRenderingOptions encoderOptions)
int size(const Forest< T > &forest)
QIcon loadIcon(const QString &name)
void updateIconCommon(QObject *object)
void updateIcon(QAbstractButton *button)
QFont normalFont()
Gets a font for normal UI widgets to use.
QFont dockFont()
Gets a font with a smallish font size for dock widgets to use.
rgba palette[MAX_PALETTE]
virtual void updateSettings()
void blockIfImageIsBusy()
QString icon
icon used in the sidebar. If left empty it will use the unknown icon
QString title
title used in the sidebar. If left empty it will be displayed as "Custom Document"
QWidget * widget
Pointer to the custom document widget.
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
bool framesNeedRelocation() const
QList< int > renderedFrameTargetTimes
QStringList renderedFrameFiles