KUIViewer: show all widget types in-pane, using QMdiArea

fix also taking screenshots via commandline, by querying the part
directly to deliver the pixmap, via a special private interface
parent f4d69f5d
......@@ -21,6 +21,7 @@
#include "kuiviewer.h"
#include "kuiviewer_part.h"
#include "kuiviewer_part_interface.h"
// KF
#include <KActionCollection>
......@@ -124,23 +125,16 @@ void KUIViewer::fileOpen()
void KUIViewer::takeScreenshot(const QString& filename, int w, int h)
{
if (!m_part) {
auto uiviewerInterface = qobject_cast<KUIViewerPartInterface*>(m_part);
if (!uiviewerInterface) {
return;
}
showMinimized();
if (w != -1 && h != -1) {
// resize widget to the desired size
m_part->widget()->setMinimumSize(w, h);
m_part->widget()->setMaximumSize(w, h);
m_part->widget()->repaint();
// resize app to be as large as desired size
adjustSize();
// Disable the saving of the size
setAutoSaveSettings(QStringLiteral("MainWindow"), false);
uiviewerInterface->setWidgetSize(QSize(w, h));
}
const QPixmap pixmap = m_part->widget()->grab();
const QPixmap pixmap = uiviewerInterface->renderWidgetAsPixmap();
pixmap.save(filename, "PNG");
}
......@@ -2,6 +2,7 @@
* This file is part of the kuiviewer package
* Copyright (c) 2003 Richard Moore <rich@kde.org>
* Copyright (c) 2003 Ian Reinhart Geiser <geiseri@kde.org>
* Copyright (c) 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -41,7 +42,9 @@
#include <QFormBuilder>
#include <QStyle>
#include <QStyleFactory>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QMdiArea>
#include <QMdiSubWindow>
K_PLUGIN_FACTORY(KUIViewerPartFactory, registerPlugin<KUIViewerPart>();)
......@@ -50,6 +53,8 @@ KUIViewerPart::KUIViewerPart(QWidget* parentWidget,
QObject* parent,
const QVariantList& /*args*/)
: KParts::ReadOnlyPart(parent)
, m_subWindow(nullptr)
, m_view(nullptr)
{
// we need an instance
KAboutData about(QStringLiteral("kuiviewerpart"),
......@@ -62,9 +67,9 @@ KUIViewerPart::KUIViewerPart(QWidget* parentWidget,
setComponentData(about);
// this should be your custom internal widget
m_widget = new QWidget(parentWidget);
QVBoxLayout* widgetVBoxLayout = new QVBoxLayout(m_widget);
widgetVBoxLayout->setMargin(0);
m_widget = new QMdiArea(parentWidget);
m_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_widget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// notify the part that this is our internal widget
setWidget(m_widget);
......@@ -133,24 +138,56 @@ bool KUIViewerPart::openFile()
{
// m_file is always local so we can use QFile on it
QFile file(localFilePath());
if (!file.open(QIODevice::ReadOnly)) {
if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
qCDebug(KUIVIEWERPART) << "Could not open UI file: " << file.errorString();
return false;
}
delete m_view;
if (m_subWindow) {
m_widget->removeSubWindow(m_subWindow);
delete m_view;
delete m_subWindow;
m_subWindow = nullptr;
}
QFormBuilder builder;
builder.setPluginPath(designerPluginPaths());
m_view = builder.load(&file, m_widget);
m_view = builder.load(&file, nullptr);
file.close();
updateActions();
if (!m_view) {
qCDebug(KUIVIEWERPART) << "Could not load UI file: " << builder.errorString();
return false;
}
m_view->show();
slotStyle(0);
// hack ahead:
// UI files have a size set for the widget they define. The QMdiSubWindow relies on sizeHint()
// during the show event though it seems, to calculate the initial window size, and then discards
// the widget size initially set from the builder in the following layout-ruled geometry update.
// Enforcing the initial size by manually setting it afterwards to the widget itself seems not possible,
// due to the layout government based on window size.
// To inject the initial widget size into the initial window geometry, as hack the min and max sizes are
// temporarily set to the wanted size and, once the window is shown, reset to their initial values.
const QSize widgetSize = m_view->size();
const QSize origWidgetMinimumSize = m_view->minimumSize();
const QSize origWidgetMaximumSize = m_view->maximumSize();
restyleView(m_style->currentText());
m_view->setMinimumSize(widgetSize);
m_view->setMaximumSize(widgetSize);
const Qt::WindowFlags windowFlags(Qt::SubWindow|Qt::CustomizeWindowHint|Qt::WindowTitleHint);
m_subWindow = m_widget->addSubWindow(m_view, windowFlags);
// prevent focus stealing by adding the window in disabled state
m_subWindow->setEnabled(false);
m_subWindow->show();
// and restore minimum size
m_view->setMinimumSize(origWidgetMinimumSize);
m_view->setMaximumSize(origWidgetMaximumSize);
m_widget->setActiveSubWindow(m_subWindow);
m_subWindow->setEnabled(true);
return true;
}
......@@ -163,28 +200,59 @@ void KUIViewerPart::updateActions()
m_copy->setEnabled(hasView);
}
void KUIViewerPart::slotStyle(int)
void KUIViewerPart::restyleView(const QString& styleName)
{
QStyle* style = QStyleFactory::create(styleName);
m_view->setStyle(style);
const QList<QWidget*> childWidgets = m_view->findChildren<QWidget*>();
for (auto child : childWidgets) {
child->setStyle(style);
}
}
void KUIViewerPart::setWidgetSize(const QSize& size)
{
if (m_view.isNull()) {
updateActions();
return;
}
const QString styleName = m_style->currentText();
QStyle* style = QStyleFactory::create(styleName);
qCDebug(KUIVIEWERPART) << "Change style: " << styleName;
// hack: enforce widget size by setting min/max sizes to wanted size
// and then have layout update the complete window
const QSize origWidgetMinimumSize = m_view->minimumSize();
const QSize origWidgetMaximumSize = m_view->maximumSize();
m_view->setMinimumSize(size);
m_view->setMaximumSize(size);
m_subWindow->updateGeometry();
// restore
m_view->setMinimumSize(origWidgetMinimumSize);
m_view->setMaximumSize(origWidgetMaximumSize);
}
QPixmap KUIViewerPart::renderWidgetAsPixmap() const
{
if (m_view.isNull()) {
return QPixmap();
}
m_widget->hide();
QApplication::setOverrideCursor(Qt::WaitCursor);
m_widget->setStyle(style);
return m_view->grab();
}
const QList<QWidget*> l = m_widget->findChildren<QWidget*>();
for (int i = 0; i < l.size(); ++i) {
l.at(i)->setStyle(style);
void KUIViewerPart::slotStyle(int)
{
if (m_view.isNull()) {
updateActions();
return;
}
m_widget->show();
QApplication::restoreOverrideCursor();
m_view->hide();
const QString styleName = m_style->currentText();
qCDebug(KUIVIEWERPART) << "Style selectd:" << styleName;
restyleView(styleName);
m_view->show();
/* the style changed, update the configuration */
if (m_styleFromConfig != styleName) {
......@@ -208,7 +276,7 @@ void KUIViewerPart::slotGrab()
return;
}
const QPixmap pixmap = m_widget->grab();
const QPixmap pixmap = m_view->grab();
QApplication::clipboard()->setPixmap(pixmap);
}
......
......@@ -2,6 +2,7 @@
* This file is part of the kuiviewer package
* Copyright (c) 2003 Richard Moore <rich@kde.org>
* Copyright (c) 2003 Ian Reinhart Geiser <geiseri@kde.org>
* Copyright (c) 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -21,12 +22,17 @@
#ifndef KUIVIEWERPART_H
#define KUIVIEWERPART_H
#include "kuiviewer_part_interface.h"
// KF
#include <KParts/ReadOnlyPart>
// Qt
#include <QPointer>
#include <QSize>
class KSelectAction;
class QMdiArea;
class QMdiSubWindow;
/**
* This is a "Part". It that does all the real work in a KPart
......@@ -36,9 +42,10 @@ class KSelectAction;
* @author Richard Moore <rich@kde.org>
* @version 0.1
*/
class KUIViewerPart : public KParts::ReadOnlyPart
class KUIViewerPart : public KParts::ReadOnlyPart, public KUIViewerPartInterface
{
Q_OBJECT
Q_INTERFACES(KUIViewerPartInterface)
public:
/**
......@@ -56,6 +63,10 @@ public Q_SLOTS:
void slotGrab();
void updateActions();
public:
void setWidgetSize(const QSize& size) override;
QPixmap renderWidgetAsPixmap() const override;
protected:
/**
* This must be implemented by each part
......@@ -63,7 +74,11 @@ protected:
bool openFile() override;
private:
QWidget* m_widget;
void restyleView(const QString& styleName);
private:
QMdiArea* m_widget;
QMdiSubWindow* m_subWindow;
QPointer<QWidget> m_view;
KSelectAction* m_style;
QAction* m_copy;
......
/*
* This file is part of the kuiviewer package
* Copyright (c) 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation.
*
* 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.
*/
#ifndef KUIVIEWERPARTINTERFACE_H
#define KUIVIEWERPARTINTERFACE_H
#include <QObject>
class QPixmap;
class QSize;
class KUIViewerPartInterface
{
public:
virtual ~KUIViewerPartInterface() {}
virtual void setWidgetSize(const QSize& size) = 0;
virtual QPixmap renderWidgetAsPixmap() const = 0;
};
Q_DECLARE_INTERFACE(KUIViewerPartInterface, "org.kde.KUIViewerPartInterface")
#endif // KUIVIEWERPARTINTERFACE_H
......@@ -76,16 +76,24 @@ int main(int argc, char** argv)
KUIViewer* widget = new KUIViewer;
widget->show();
} else {
const bool takeScreenshot = parser.isSet(takeScreenshotOptionKey);
KUIViewer* widget = new KUIViewer;
// show before loading, so widget geometries will be properly updated when requested
// TODO: investigate how to do this properly with perhaps showevents & Co.?
if (takeScreenshot) {
widget->showMinimized();
} else {
widget->show();
}
widget->load(QUrl::fromUserInput(positionalArguments.at(0), QDir::currentPath()));
if (parser.isSet(takeScreenshotOptionKey)) {
if (takeScreenshot) {
widget->takeScreenshot(parser.value(takeScreenshotOptionKey),
parser.value(screenshotWidthOptionKey).toInt(),
parser.value(screenshotHeightOptionKey).toInt());
return 0;
}
widget->show();
}
}
......
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