Commit 3b4cd767 authored by Jouni Pentikäinen's avatar Jouni Pentikäinen

Save geometry of detached canvas window to window layouts and sessions

parent 8673d24e
......@@ -673,8 +673,15 @@ void KisMainWindow::slotThemeChanged()
emit themeChanged();
}
void KisMainWindow::slotDetachCanvas(bool detach)
bool KisMainWindow::canvasDetached() const
{
return centralWidget() != d->mdiArea;
}
void KisMainWindow::setCanvasDetached(bool detach)
{
if (detach == canvasDetached()) return;
QWidget *outgoingWidget = takeCentralWidget();
QWidget *incomingWidget = d->canvasWindow->layout()->takeAt(0)->widget();
......@@ -688,6 +695,13 @@ void KisMainWindow::slotDetachCanvas(bool detach)
KIS_SAFE_ASSERT_RECOVER_NOOP(incomingWidget == d->mdiArea);
d->canvasWindow->hide();
}
d->toggleDetachCanvas->setChecked(detach);
}
QWidget * KisMainWindow::canvasWindow() const
{
return d->canvasWindow;
}
void KisMainWindow::updateReloadFileAction(KisDocument *doc)
......@@ -2520,7 +2534,7 @@ void KisMainWindow::createActions()
d->toggleDetachCanvas = actionManager->createAction("view_detached_canvas");
d->toggleDockerTitleBars->setChecked(false);
connect(d->toggleDetachCanvas, SIGNAL(toggled(bool)), SLOT(slotDetachCanvas(bool)));
connect(d->toggleDetachCanvas, SIGNAL(toggled(bool)), SLOT(setCanvasDetached(bool)));
actionCollection()->addAction("settings_dockers_menu", d->dockWidgetMenu);
actionCollection()->addAction("window", d->windowMenu);
......
......@@ -165,6 +165,12 @@ public:
QStringList showOpenFileDialog(bool isImporting);
/**
* The top-level window used for a detached canvas.
*/
QWidget *canvasWindow() const;
bool canvasDetached() const;
/**
* Shows if the main window is saving anything right now. If the
* user presses Ctrl+W too fast, then the document can be close
......@@ -257,6 +263,11 @@ public Q_SLOTS:
void notifyChildViewDestroyed(KisView *view);
/**
* Detach canvas onto a separate window, or restore it back to to main window.
*/
void setCanvasDetached(bool detached);
private Q_SLOTS:
/**
* Save the list of recent files.
......@@ -363,8 +374,6 @@ private Q_SLOTS:
*/
void slotThemeChanged();
void slotDetachCanvas(bool detached);
void undo();
void redo();
void updateWindowMenu();
......
......@@ -35,12 +35,80 @@ static const int WINDOW_LAYOUT_VERSION = 1;
struct KisWindowLayoutResource::Private
{
struct WindowGeometry{
int screen = -1;
Qt::WindowStates stateFlags = Qt::WindowNoState;
QByteArray data;
static WindowGeometry fromWindow(const QWidget *window, QList<QScreen*> screens)
{
WindowGeometry geometry;
QWindow *windowHandle = window->windowHandle();
geometry.data = window->saveGeometry();
geometry.stateFlags = windowHandle->windowState();
int index = screens.indexOf(windowHandle->screen());
if (index >= 0) {
geometry.screen = index;
}
return geometry;
}
void forceOntoCorrectScreen(QWidget *window, QList<QScreen*> screens)
{
QWindow *windowHandle = window->windowHandle();
if (screens.indexOf(windowHandle->screen()) != screen) {
QScreen *qScreen = screens[screen];
windowHandle->setScreen(qScreen);
windowHandle->setPosition(qScreen->availableGeometry().topLeft());
}
if (stateFlags) {
window->setWindowState(stateFlags);
}
}
void save(QDomDocument &doc, QDomElement &elem) const
{
if (screen >= 0) {
elem.setAttribute("screen", screen);
}
if (stateFlags & Qt::WindowMaximized) {
elem.setAttribute("maximized", "1");
}
QDomElement geometry = doc.createElement("geometry");
geometry.appendChild(doc.createCDATASection(data.toBase64()));
elem.appendChild(geometry);
}
static WindowGeometry load(const QDomElement &element)
{
WindowGeometry geometry;
geometry.screen = element.attribute("screen", "-1").toInt();
if (element.attribute("maximized", "0") != "0") {
geometry.stateFlags |= Qt::WindowMaximized;
}
QDomElement dataElement = element.firstChildElement("geometry");
geometry.data = QByteArray::fromBase64(dataElement.text().toLatin1());
return geometry;
}
};
struct Window {
QUuid windowId;
QByteArray geometry;
QByteArray windowState;
int screen = -1;
Qt::WindowStates stateFlags = Qt::WindowNoState;
WindowGeometry geometry;
bool canvasDetached = false;
WindowGeometry canvasWindowGeometry;
};
QVector<Window> windows;
......@@ -192,27 +260,31 @@ void KisWindowLayoutResource::applyLayout()
QPointer<KisMainWindow> mainWindow = kisPart->windowById(window.windowId);
KIS_SAFE_ASSERT_RECOVER_BREAK(mainWindow);
mainWindow->restoreGeometry(window.geometry);
mainWindow->restoreGeometry(window.geometry.data);
mainWindow->restoreWorkspaceState(window.windowState);
mainWindow->setCanvasDetached(window.canvasDetached);
if (window.canvasDetached) {
QWidget *canvasWindow = mainWindow->canvasWindow();
mainWindow->restoreGeometry(window.canvasWindowGeometry.data);
}
}
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
QList<QScreen*> screens = d->getScreensInConsistentOrder();
Q_FOREACH(const auto &window, d->windows) {
if (window.screen >= 0 && window.screen < screens.size()) {
QPointer<KisMainWindow> mainWindow = kisPart->windowById(window.windowId);
KIS_SAFE_ASSERT_RECOVER_BREAK(mainWindow);
QWindow *windowHandle = mainWindow->windowHandle();
if (screens.indexOf(windowHandle->screen()) != window.screen) {
QScreen *screen = screens[window.screen];
windowHandle->setScreen(screen);
windowHandle->setPosition(screen->availableGeometry().topLeft());
}
Private::WindowGeometry geometry = window.geometry;
QPointer<KisMainWindow> mainWindow = kisPart->windowById(window.windowId);
KIS_SAFE_ASSERT_RECOVER_BREAK(mainWindow);
if (window.stateFlags) {
mainWindow->setWindowState(window.stateFlags);
if (geometry.screen >= 0 && geometry.screen < screens.size()) {
geometry.forceOntoCorrectScreen(mainWindow, screens);
}
if (window.canvasDetached) {
Private::WindowGeometry canvasWindowGeometry = window.canvasWindowGeometry;
if (canvasWindowGeometry.screen >= 0 && canvasWindowGeometry.screen < screens.size()) {
canvasWindowGeometry.forceOntoCorrectScreen(mainWindow->canvasWindow(), screens);
}
}
}
......@@ -298,18 +370,14 @@ void KisWindowLayoutResource::saveXml(QDomDocument &doc, QDomElement &root) cons
QDomElement elem = doc.createElement("window");
elem.setAttribute("id", window.windowId.toString());
if (window.screen >= 0) {
elem.setAttribute("screen", window.screen);
}
window.geometry.save(doc, elem);
if (window.stateFlags & Qt::WindowMaximized) {
elem.setAttribute("maximized", "1");
if (window.canvasDetached) {
QDomElement canvasWindowElement = doc.createElement("canvasWindow");
window.canvasWindowGeometry.save(doc, canvasWindowElement);
elem.appendChild(canvasWindowElement);
}
QDomElement geometry = doc.createElement("geometry");
geometry.appendChild(doc.createCDATASection(window.geometry.toBase64()));
elem.appendChild(geometry);
QDomElement state = doc.createElement("windowState");
state.appendChild(doc.createCDATASection(window.windowState.toBase64()));
elem.appendChild(state);
......@@ -334,16 +402,15 @@ void KisWindowLayoutResource::loadXml(const QDomElement &element) const
window.windowId = QUuid::createUuid();
}
window.screen = windowElement.attribute("screen", "-1").toInt();
window.geometry = Private::WindowGeometry::load(windowElement);
if (windowElement.attribute("maximized", "0") != "0") {
window.stateFlags |= Qt::WindowMaximized;
QDomElement canvasWindowElement = windowElement.firstChildElement("canvasWindow");
if (!canvasWindowElement.isNull()) {
window.canvasDetached = true;
window.canvasWindowGeometry = Private::WindowGeometry::load(canvasWindowElement);
}
QDomElement geometry = windowElement.firstChildElement("geometry");
QDomElement state = windowElement.firstChildElement("windowState");
window.geometry = QByteArray::fromBase64(geometry.text().toLatin1());
window.windowState = QByteArray::fromBase64(state.text().toLatin1());
d->windows.append(window);
......@@ -366,16 +433,12 @@ void KisWindowLayoutResource::setWindows(const QList<QPointer<KisMainWindow>> &m
Private::Window state;
state.windowId = window->id();
state.geometry = window->saveGeometry();
state.windowState = window->saveState();
state.stateFlags = window->windowState();
state.geometry = Private::WindowGeometry::fromWindow(window, screens);
QWindow *windowHandle = window->windowHandle();
if (windowHandle) {
int index = screens.indexOf(windowHandle->screen());
if (index >= 0) {
state.screen = index;
}
state.canvasDetached = window->canvasDetached();
if (state.canvasDetached) {
state.canvasWindowGeometry = Private::WindowGeometry::fromWindow(window->canvasWindow(), screens);
}
d->windows.append(state);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment