[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-games-devel
Subject: Re: [Kde-games-devel] Palapeli preview window survey
From: Johannes Loehnert <loehnert.kde () gmx ! de>
Date: 2010-08-14 9:26:43
Message-ID: 201008141126.44288.loehnert.kde () gmx ! de
[Download RAW message or body]
[Attachment #2 (multipart/signed)]
[Attachment #4 (multipart/mixed)]
Hello again,
so here is the solution I came up with originally. I had similar thoughts as
you both and made the preview a separate tool window.
* Of course it can be moved and resized ad libitum.
* It is always on top
* Hovering the mouse over the window zooms the image.¹
What's different to your proposals:
* not on by default; however if it was open on close, it will be there on
restart.
* no close button (but that's trivial)
I'm curious about your opinions. :-)
Best regards,
Johannes
¹fine print: only tested with activation-follows-mouse policy
["puzzlepreview.patch" (text/x-patch)]
Index: src/palapeli-puzzletableui.rc
===================================================================
--- src/palapeli-puzzletableui.rc (Revision 1163530)
+++ src/palapeli-puzzletableui.rc (Arbeitskopie)
@@ -7,5 +7,6 @@
<ToolBar name="puzzleTableToolbar">
<text>Puzzle table toolbar</text>
<Action name="game_restart"/>
+ <Action name="toggle_preview"/>
</ToolBar>
</gui>
Index: src/palapeli.kcfg
===================================================================
--- src/palapeli.kcfg (Revision 1163530)
+++ src/palapeli.kcfg (Arbeitskopie)
@@ -29,4 +29,14 @@
<default>true</default>
</entry>
</group>
+ <group name="PuzzlePreview">
+ <entry name="PuzzlePreviewVisible" type="Bool">
+ <label>Wether the preview window was switched on last time Palapeli was \
run.</label> + <default>false</default>
+ </entry>
+ <entry name="PuzzlePreviewGeometry" type="Rect">
+ <label>Last position and size of puzzle preview.</label>
+ <default>QRect(-1, -1, 320, 240)</default>
+ </entry>
+ </group>
</kcfg>
Index: src/engine/puzzlepreview.h
===================================================================
--- src/engine/puzzlepreview.h (Revision 0)
+++ src/engine/puzzlepreview.h (Revision 0)
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright 2010 Johannes Loehnert <loehnert.kde@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+***************************************************************************/
+
+#ifndef PALAPELI_PUZZLEPREVIEW_H
+#define PALAPELI_PUZZLEPREVIEW_H
+
+#include <QGraphicsView>
+#include <QModelIndex>
+#include <QPointer>
+#include <QTimer>
+
+
+namespace Palapeli
+{
+ class Puzzle;
+ class PuzzlePreview : public QGraphicsView
+ {
+ Q_OBJECT
+ public:
+ PuzzlePreview();
+
+ void setImage(const QImage &image);
+ void loadImageFrom(const QModelIndex &index);
+
+ public Q_SLOTS:
+ // toggles visibility state AND updates config with the new state.
+ void toggleVisible();
+
+ protected:
+ virtual void mouseMoveEvent(QMouseEvent* event);
+ virtual void enterEvent(QEvent* event);
+ virtual void leaveEvent(QEvent* event);
+ virtual void resizeEvent(QResizeEvent* event);
+ virtual void moveEvent(QMoveEvent *event);
+ void updateViewport();
+ void loadImageFromInternal(Palapeli::Puzzle *puzzle);
+
+ private Q_SLOTS:
+ void writeConfigIfGeometryChanged();
+
+ private:
+
+ QPointer<Palapeli::Puzzle> m_puzzle;
+ // used to save geometry after move/resize, to avoid writing config file each \
time the cursor moves a pixel. + QTimer* m_settingsSaveTimer;
+ bool m_geometryChanged;
+
+ qreal m_hoverZoom;
+ bool m_isZoomed;
+ QPoint m_mousePos;
+ };
+}
+
+#endif // PALAPELI_PUZZLEPREVIEW_H
Index: src/engine/puzzlepreview.cpp
===================================================================
--- src/engine/puzzlepreview.cpp (Revision 0)
+++ src/engine/puzzlepreview.cpp (Revision 0)
@@ -0,0 +1,185 @@
+/***************************************************************************
+ * Copyright 2010 Johannes Loehnert <loehnert.kde@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+***************************************************************************/
+
+#include "puzzlepreview.h"
+#include "../file-io/collection.h"
+#include "../file-io/puzzle.h"
+#include "settings.h"
+
+#include <cmath>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QDebug>
+#include <KLocalizedString>
+
+Palapeli::PuzzlePreview::PuzzlePreview()
+{
+ m_settingsSaveTimer = new QTimer(this);
+ connect(m_settingsSaveTimer, SIGNAL(timeout()), this, \
SLOT(writeConfigIfGeometryChanged())); + m_geometryChanged = false;
+
+ m_hoverZoom = 1.0;
+ m_isZoomed = false;
+ m_mousePos = QPoint();
+
+ setScene(new QGraphicsScene());
+ setWindowTitle(i18nc("tool window title", "Preview of assembled puzzle"));
+ setWindowFlags(Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowTitleHint | \
Qt::WindowStaysOnTopHint); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setRenderHint(QPainter::SmoothPixmapTransform);
+ scene()->addText(i18nc("text in preview window", "No puzzle is loaded."));
+ setSceneRect(scene()->itemsBoundingRect());
+
+ // read size and position settings
+ QRect geometry = Settings::puzzlePreviewGeometry();
+ resize(geometry.size());
+
+ // default (-1/-1) toprect: don't change position
+ if (geometry.left() >= 0 && geometry.top() >= 0)
+ move(geometry.topLeft());
+
+ m_settingsSaveTimer->start(500);
+ hide();
+ updateViewport();
+}
+
+void Palapeli::PuzzlePreview::setImage(const QImage &image)
+{
+ scene()->clear();
+ scene()->addPixmap(QPixmap::fromImage(image));
+ setSceneRect(image.rect());
+ updateViewport();
+}
+
+void Palapeli::PuzzlePreview::loadImageFrom(const QModelIndex &index)
+{
+ QObject* puzzlePayload = \
index.data(Palapeli::Collection::PuzzleObjectRole).value<QObject*>(); \
+ Palapeli::Puzzle* puzzle = qobject_cast<Palapeli::Puzzle*>(puzzlePayload); + if \
(puzzle && m_puzzle != puzzle) + {
+ m_puzzle = puzzle;
+ loadImageFromInternal(puzzle);
+ }
+}
+
+void Palapeli::PuzzlePreview::loadImageFromInternal(Palapeli::Puzzle *puzzle)
+{
+ // metadata was assumedly loaded by Palapeli::Scene.
+ // FIXME: possible race condition? in case of doubt, how to wait for metadata?
+ // (would have to catch Scene::m_metadataLoader finished() --> bad design!)
+ // (or, use a timer and look every x ms if we can proceed)
+ if (puzzle->metadata())
+ {
+ setImage(puzzle->metadata()->image);
+
+ // set hover zoom so that 3x3 pieces would be visible on a square grid.
+ m_hoverZoom = sqrt(puzzle->metadata()->pieceCount)/3.0;
+ if (m_hoverZoom < 1)
+ m_hoverZoom = 1;
+ }
+ else
+ {
+ qWarning() << "cannot set image: metadata not loaded";
+ }
+}
+
+void Palapeli::PuzzlePreview::toggleVisible()
+{
+ setVisible(!isVisible());
+ Settings::setPuzzlePreviewVisible(isVisible());
+ Settings::self()->writeConfig();
+}
+
+void Palapeli::PuzzlePreview::mouseMoveEvent(QMouseEvent* event)
+{
+ m_mousePos = event->pos();
+ updateViewport();
+ QGraphicsView::mouseMoveEvent(event);
+}
+
+void Palapeli::PuzzlePreview::enterEvent(QEvent* event)
+{
+ setMouseTracking(true);
+ m_isZoomed = true;
+ m_mousePos = QPoint();
+ // wait with update for first mouseMoveEvent
+ QGraphicsView::enterEvent(event);
+}
+
+void Palapeli::PuzzlePreview::leaveEvent(QEvent* event)
+{
+ setMouseTracking(false);
+ m_isZoomed = false;
+ updateViewport();
+ QGraphicsView::leaveEvent(event);
+}
+
+void Palapeli::PuzzlePreview::resizeEvent(QResizeEvent* event)
+{
+ updateViewport();
+ m_geometryChanged = true;
+ QGraphicsView::resizeEvent(event);
+}
+
+void Palapeli::PuzzlePreview::moveEvent(QMoveEvent* event)
+{
+ m_geometryChanged = true;
+ QGraphicsView::moveEvent(event);
+}
+
+void Palapeli::PuzzlePreview::writeConfigIfGeometryChanged()
+{
+ if (!m_geometryChanged) return;
+
+ qDebug() << "puzzle preview: saving changed geometry";
+
+ // move() includes window frame, resize() doesn't :-/
+ Settings::setPuzzlePreviewGeometry(QRect(frameGeometry().topLeft(), size()));
+ Settings::self()->writeConfig();
+ m_geometryChanged = false;
+}
+
+
+void Palapeli::PuzzlePreview::updateViewport()
+{
+ qreal zoom;
+ // calculate zoom for fit-in-window
+ zoom = width() / sceneRect().width();
+ if (zoom > height() / sceneRect().height())
+ zoom = height() / sceneRect().height();
+
+ if (m_isZoomed)
+ zoom *= m_hoverZoom;
+
+ // do not enlarge
+ if (zoom>1)
+ zoom = 1;
+
+ resetTransform();
+ scale(zoom, zoom);
+
+ if (m_isZoomed)
+ {
+ // focus moves with cursor position
+ QPointF pos = m_mousePos;
+ pos.rx() *= sceneRect().width() / width();
+ pos.ry() *= sceneRect().height() / height();
+ centerOn(pos);
+ }
+}
\ No newline at end of file
Index: src/window/puzzletablewidget.cpp
===================================================================
--- src/window/puzzletablewidget.cpp (Revision 1163530)
+++ src/window/puzzletablewidget.cpp (Arbeitskopie)
@@ -18,6 +18,7 @@
#include "puzzletablewidget.h"
#include "loadingwidget.h"
+#include "../engine/puzzlepreview.h"
#include "../engine/scene.h"
#include "../engine/view.h"
#include "../engine/zoomwidget.h"
@@ -56,12 +57,17 @@
, m_view(new Palapeli::View)
, m_progressBar(new Palapeli::TextProgressBar(this))
, m_zoomWidget(new Palapeli::ZoomWidget(this))
+ , m_puzzlePreview(new Palapeli::PuzzlePreview())
{
//setup actions
KAction* restartPuzzleAct = new KAction(KIcon("view-refresh"), i18n("&Restart \
puzzle..."), 0); restartPuzzleAct->setToolTip(i18n("Delete the saved progress"));
actionCollection()->addAction("game_restart", restartPuzzleAct);
connect(restartPuzzleAct, SIGNAL(triggered()), m_view->scene(), \
SLOT(restartPuzzle())); + KAction* togglePreviewAct = new \
KAction(KIcon("view-preview"), i18n("Toggle image &preview"), 0); \
+ togglePreviewAct->setToolTip(i18n("Shows or hides the image of the assembled \
puzzle")); + actionCollection()->addAction("toggle_preview", togglePreviewAct);
+ connect(togglePreviewAct, SIGNAL(triggered()), m_puzzlePreview, \
SLOT(toggleVisible())); setupGUI();
//setup progress bar
m_progressBar->setText(i18n("No puzzle loaded"));
@@ -95,6 +101,11 @@
return m_view;
}
+Palapeli::PuzzlePreview* Palapeli::PuzzleTableWidget::puzzlePreview() const
+{
+ return m_puzzlePreview;
+}
+
void Palapeli::PuzzleTableWidget::showStatusBar(bool visible)
{
//apply setting
Index: src/window/puzzletablewidget.h
===================================================================
--- src/window/puzzletablewidget.h (Revision 1163530)
+++ src/window/puzzletablewidget.h (Arbeitskopie)
@@ -28,6 +28,7 @@
class LoadingWidget;
class TextProgressBar;
class View;
+ class PuzzlePreview;
class ZoomWidget;
class PuzzleTableWidget : public Palapeli::TabWindow
@@ -37,6 +38,7 @@
PuzzleTableWidget();
Palapeli::View* view() const;
+ Palapeli::PuzzlePreview* puzzlePreview() const;
public Q_SLOTS:
void reportProgress(int pieceCount, int partCount);
void showStatusBar(bool visible);
@@ -49,6 +51,7 @@
Palapeli::View* m_view;
Palapeli::TextProgressBar* m_progressBar;
Palapeli::ZoomWidget* m_zoomWidget;
+ Palapeli::PuzzlePreview* m_puzzlePreview;
};
}
Index: src/window/mainwindow.cpp
===================================================================
--- src/window/mainwindow.cpp (Revision 1163530)
+++ src/window/mainwindow.cpp (Arbeitskopie)
@@ -19,6 +19,7 @@
#include "mainwindow.h"
#include "../config/configdialog.h"
#include "../creator/puzzlecreator.h"
+#include "../engine/puzzlepreview.h"
#include "../engine/scene.h"
#include "../engine/view.h"
#include "collectionwidget.h"
@@ -158,6 +159,8 @@
void Palapeli::MainWindow::loadPuzzle(const QModelIndex& index)
{
m_puzzleTable->view()->scene()->loadPuzzle(index);
+ m_puzzleTable->puzzlePreview()->loadImageFrom(index);
+ m_puzzleTable->puzzlePreview()->setVisible(Settings::puzzlePreviewVisible());
m_centralWidget->setTabEnabled(m_centralWidget->indexOf(m_puzzleTable), true);
m_centralWidget->setCurrentWidget(m_puzzleTable);
setCaption(index.data(Qt::DisplayRole).toString());
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt (Revision 1163530)
+++ src/CMakeLists.txt (Arbeitskopie)
@@ -19,6 +19,7 @@
engine/mergegroup.cpp
engine/piece.cpp
engine/piecevisuals.cpp
+ engine/puzzlepreview.cpp
engine/scene.cpp
engine/texturehelper.cpp
engine/trigger.cpp
["signature.asc" (application/pgp-signature)]
_______________________________________________
kde-games-devel mailing list
kde-games-devel@kde.org
https://mail.kde.org/mailman/listinfo/kde-games-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic