foreach and qDeleteAll know how to iterate over qmaps, so do not use values, it's...
[kdepim.git] / kode / kxforms / editor / editorwidget.cpp
blob96f7ad3c5be13f32f48fbaa6eb26b3e2f7986e07
1 /*
2 This file is part of KXForms.
4 Copyright (c) 2007 Andre Duffeck <aduffeck@suse.de>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
22 #include "editorwidget.h"
23 #include "editor.h"
24 #include "globalsettingsdlg.h"
25 #include "positionaction.h"
26 #include "../manager.h"
27 #include "../formgui.h"
29 #include <kdebug.h>
30 #include <kactionmenu.h>
31 #include <kmenu.h>
32 #include <klocale.h>
33 #include <kiconloader.h>
35 #include <QTimer>
36 #include <QPoint>
37 #include <QPainter>
38 #include <QMouseEvent>
39 #include <QPushButton>
40 #include <QEventLoop>
41 #include <QWhatsThis>
42 #include <QVBoxLayout>
43 #include <QApplication>
45 using namespace KXForms;
47 EditorWidget::EditorWidget( Editor *e, FormGui *parent )
48 : QWidget( parent ), mEditor( e ), mGui( parent ), mHoveredElement( 0 ), mActiveElement( 0 ),
49 mEventLoop( new QEventLoop( this ) ), mInSelection( false ), mInEdit( false ),
50 mDraggedElement( 0 )
52 setMouseTracking( true );
53 setGeometry( parent->geometry() );
54 init();
57 void EditorWidget::init()
59 mInterfaceWidget = new QWidget( this );
60 QVBoxLayout *vbl = new QVBoxLayout( mInterfaceWidget );
61 vbl->setMargin( 0 );
63 mShowHintsButton = new QPushButton( mInterfaceWidget );
64 mShowHintsButton->setIcon( KIconLoader::global()->loadIcon( "document-preview", KIconLoader::NoGroup, 32 ) );
65 mShowHintsButton->setToolTip( i18n("Show hints") );
66 connect( mShowHintsButton, SIGNAL(clicked()), SLOT(showHints()) );
67 vbl->addWidget( mShowHintsButton );
70 mSaveHintsButton = new QPushButton( mInterfaceWidget );
71 mSaveHintsButton->setIcon( KIconLoader::global()->loadIcon( "document-save", KIconLoader::NoGroup, 32 ) );
72 mSaveHintsButton->setToolTip( i18n("Save hints") );
73 connect( mSaveHintsButton, SIGNAL(clicked()), mEditor, SLOT(saveHints()) );
74 vbl->addWidget( mSaveHintsButton );
76 mSaveHintsAsButton = new QPushButton( mInterfaceWidget );
77 mSaveHintsAsButton->setIcon( KIconLoader::global()->loadIcon( "document-save-as", KIconLoader::NoGroup, 32 ) );
78 mSaveHintsAsButton->setToolTip( i18n("Save hints as...") );
79 connect( mSaveHintsAsButton, SIGNAL(clicked()), mEditor, SLOT(saveHintsAs()) );
80 vbl->addWidget( mSaveHintsAsButton );
82 mEditDefaultsButton = new QPushButton( mInterfaceWidget );
83 mEditDefaultsButton->setIcon( KIconLoader::global()->loadIcon( "configure", KIconLoader::NoGroup, 32 ) );
84 mEditDefaultsButton->setToolTip( i18n("Edit global settings") );
85 connect( mEditDefaultsButton, SIGNAL(clicked()), SLOT(editDefaults()) );
86 vbl->addWidget( mEditDefaultsButton );
88 mExitButton = new QPushButton( this );
89 mExitButton->setIcon( KIconLoader::global()->loadIcon( "dialog-cancel", KIconLoader::NoGroup, 32 ) );
90 mExitButton->setToolTip( i18n("Quit edit mode") );
91 connect( mExitButton, SIGNAL(clicked()), mEditor, SLOT(toggleEditMode()) );
92 vbl->addWidget( mExitButton );
94 mEditButton = new QPushButton( this );
95 mEditButton->setIcon( KIconLoader::global()->loadIcon( "document-properties", KIconLoader::NoGroup, 32 ) );
96 mEditButton->hide();
97 mEditButton->setToolTip( i18n("Edit element") );
98 connect( mEditButton, SIGNAL(clicked()), SLOT(showActionMenu()) );
101 void EditorWidget::setGuiElements( const GuiElement::List &list )
103 foreach( GuiElement *e, list ) {
104 QRect r = e->widget()->geometry();
105 if( e->labelWidget() )
106 r |= e->labelWidget()->geometry();
107 QPoint widgetPos = e->widget()->mapToGlobal(QPoint(0,0)) - mapToGlobal(QPoint(0,0));
108 QPoint labelWidgetPos = e->labelWidget() ? e->labelWidget()->mapToGlobal(QPoint(0,0)) - mapToGlobal(QPoint(0,0)) : widgetPos;
109 r.moveTop( qMin( widgetPos.y(), labelWidgetPos.y() ) );
110 r.moveLeft( qMin( widgetPos.x(), labelWidgetPos.x() ) );
112 mElementMap[e] = r;
113 mGroupMap[e->properties()->group] |= r;
117 void EditorWidget::setInEdit( bool b )
119 mInEdit = b;
120 if( !b )
121 mActiveElement = 0;
124 void EditorWidget::mouseMoveEvent( QMouseEvent *event )
126 // kDebug() ;
127 GuiElement *newElement = 0;
128 QPoint pos = event->pos();
131 if( mInDrag && !mDraggedElement && ( mDragPoint - pos ).manhattanLength() > QApplication::startDragDistance() ) {
132 foreach( const QRect &dragR, mElementMap ) {
133 if( dragR.contains( mDragPoint ) ) {
134 if( !mDraggedElement ||
135 mElementMap[ mDraggedElement ].width() > dragR.width() ||
136 mElementMap[ mDraggedElement ].height() > dragR.height() ) {
137 mDraggedElement = mElementMap.key( dragR );
141 QPixmap cursorPixmap = QPixmap::grabWidget( mGui, mElementMap[ mDraggedElement ] ).scaled( 300, 300, Qt::KeepAspectRatio );
142 QApplication::setOverrideCursor( QCursor( cursorPixmap ) );
143 mActiveElement = mDraggedElement;
144 mInEdit = true;
145 mInSelection = true;
146 mSelectionMode = Editor::SelectSameGroupOnly;
149 foreach( const QRect &r, mElementMap ) {
150 if( r.contains( pos ) ) {
151 if( !newElement ||
152 mElementMap[ newElement ].width() > r.width() ||
153 mElementMap[ newElement ].height() > r.height() ) {
154 newElement = mElementMap.key( r );
158 if( mHoveredElement != newElement ) {
159 mHoveredElement = newElement;
160 update();
164 void EditorWidget::mousePressEvent( QMouseEvent *event )
166 // kDebug() ;
167 mDragPoint = event->pos();
168 mInDrag = true;
171 void EditorWidget::mouseReleaseEvent( QMouseEvent *event )
173 Q_UNUSED( event )
174 // kDebug() ;
176 if( mInDrag ) {
177 mInDrag = false;
178 QApplication::restoreOverrideCursor();
179 if( mDraggedElement && mHoveredElement &&
180 mDraggedElement != mHoveredElement &&
181 mHoveredElement->properties()->group == mActiveElement->properties()->group) {
182 PositionAction *a = dynamic_cast<PositionAction *>(mEditor->action( "edit_position" ));
183 if( a )
184 a->perform( mDraggedElement, mHoveredElement );
187 mDraggedElement = 0;
189 if( !mInSelection )
190 return;
192 if( mEventLoop->isRunning() ) {
193 mEventLoop->exit();
195 mInSelection = false;
198 void EditorWidget::paintEvent( QPaintEvent *event )
200 Q_UNUSED( event )
201 // kDebug() ;
202 QPainter p( this );
204 drawGroups( &p );
205 drawWidgetFrames( &p );
207 if( mInSelection ) {
208 if( mHoveredElement != mActiveElement ) {
209 if( mHoveredElement && mActiveElement->properties()->group != mHoveredElement->properties()->group )
210 printMessage( &p, mElementMap[mHoveredElement], i18n("Groups do not match: %1 != %2", mActiveElement->properties()->group,
211 mHoveredElement->properties()->group));
212 else
213 targetElement( &p, mElementMap[mHoveredElement], mHoveredElement );
217 if( !mInEdit ) {
218 if( mHoveredElement ) {
219 highlightElement( &p, mElementMap[mHoveredElement], mHoveredElement );
220 drawInterface( &p, mElementMap[mHoveredElement], mHoveredElement );
221 } else {
222 mEditButton->hide();
224 } else {
225 if( mActiveElement ) {
226 highlightElement( &p, mElementMap[mActiveElement], mActiveElement );
230 drawGlobalInterface( &p );
233 void EditorWidget::drawGlobalInterface( QPainter *p )
235 p->save();
237 QBrush b( QColor(0,0,0,25) );
238 p->fillRect( rect(), b );
240 mInterfaceWidget->move( width() - mInterfaceWidget->width()-10, 10 );
241 QRect r( width() - mInterfaceWidget->width() - 15, 5, mInterfaceWidget->width()+10, mInterfaceWidget->height()+10 );
243 QPen pen;
244 pen.setColor( QColor(255,255,255,255) );
245 pen.setWidth( 2 );
246 b.setColor( QColor(0,0,0,100) );
247 p->setPen( pen );
248 p->setBrush( b );
249 p->drawRoundRect( r );
251 p->restore();
254 void EditorWidget::drawGroups( QPainter *p )
256 p->save();
258 QList<QRect> alreadyPaintedRects;
260 QBrush b( QColor(200,200,50,50) );
261 QPen pen;
262 pen.setColor( QColor(50,50,0,255) );
263 pen.setWidth( 3 );
264 p->setPen( pen );
265 p->setBrush( b );
267 QFont fnt;
268 fnt.setPointSize( 14 );
269 fnt.setBold( true );
270 p->setFont( fnt );
272 foreach( QString group, mGroupMap.keys() ) {
273 p->save();
274 QBrush b2 = b;
275 foreach( QRect otherRect, alreadyPaintedRects ) {
276 if( mGroupMap[group].intersects( otherRect ) ) {
277 b2 = QBrush( QColor(0,200,0,50) );
278 QPen pen2;
279 pen2.setColor( QColor(50,150,50,255) );
280 pen2.setWidth( 3 );
281 p->setPen( pen2 );
282 break;
285 p->fillRect( mGroupMap[group], b2 );
286 p->drawText( mGroupMap[group].center(), i18n("Group: %1", group ) );
287 alreadyPaintedRects.append( mGroupMap[group] );
288 p->restore();
290 p->restore();
293 void EditorWidget::drawWidgetFrames( QPainter *p )
295 p->save();
297 QPen pen;
298 pen.setColor( QColor(50,50,50,150) );
299 pen.setWidth( 1 );
300 p->setPen( pen );
302 foreach( const QRect &r, mElementMap ) {
303 p->drawRect( r );
306 p->restore();
309 void EditorWidget::targetElement( QPainter *p, const QRect &r, GuiElement *w )
311 p->save();
313 QPen pen;
314 pen.setColor( QColor(255,0,0,255) );
315 pen.setWidth( 3 );
316 p->setPen( pen );
317 p->drawRect( r );
319 QBrush b( QColor(0,0,0,50) );
320 p->fillRect( r, b );
322 if( w ) {
323 QPoint point( r.x()+20, r.y() );
324 QFont fnt;
325 fnt.setPointSize( 14 );
326 fnt.setBold( true );
327 p->setFont( fnt );
328 p->drawText( point + QPoint(0,QFontMetrics( fnt ).height() ), w->id().toString() );
331 p->restore();
334 void EditorWidget::highlightElement( QPainter *p, const QRect &r, GuiElement *w )
336 p->save();
338 QPoint point( r.x()+30+mEditButton->sizeHint().width(), r.y() );
340 QPen pen;
341 pen.setColor( QColor(255,255,255,255) );
342 pen.setWidth( 3 );
343 p->setPen( pen );
344 p->drawRect( r );
346 QBrush b( QColor(0,0,0,100) );
347 p->fillRect( r, b );
349 QFont fnt;
350 fnt.setPointSize( 14 );
351 fnt.setBold( true );
352 p->setFont( fnt );
353 p->drawText( point + QPoint(0,QFontMetrics( fnt ).height() ), w->id().toString() );
355 p->restore();
358 void EditorWidget::printMessage( QPainter *p, const QRect &r, const QString &msg )
360 p->save();
362 QPen pen;
363 pen.setColor( QColor(0,0,0,180) );
364 pen.setWidth( 3 );
365 p->setPen( pen );
366 p->drawRect( r );
368 QBrush b( QColor(0,0,0,50) );
369 p->fillRect( r, b );
371 QPoint point( r.x()+20, r.y() );
372 QFont fnt;
373 fnt.setPointSize( 14 );
374 fnt.setBold( true );
375 p->setFont( fnt );
376 p->drawText( point + QPoint(0,QFontMetrics( fnt ).height() ), msg );
378 p->restore();
381 void EditorWidget::drawInterface( QPainter *p, const QRect &r, GuiElement *w )
383 Q_UNUSED( p );
384 Q_UNUSED( w );
386 QPoint point( r.x()+20, r.y() );
387 mEditButton->move( point );
388 mEditButton->show();
391 void EditorWidget::showActionMenu()
393 KActionMenu *menu = mEditor->actionMenu( mHoveredElement );
394 menu->menu()->popup( mapToGlobal( mEditButton->pos() ) );
395 mActiveElement = mHoveredElement;
398 void EditorWidget::showHints()
400 QString text = mEditor->hints().toRichText();
401 QWhatsThis::showText( mapToGlobal( mShowHintsButton->pos() ), text );
404 void EditorWidget::editDefaults()
406 GlobalSettingsDialog *dlg = new GlobalSettingsDialog( mEditor->manager(), this );
407 Hints hints;
409 if( dlg->exec() == QDialog::Accepted ) {
410 hints = dlg->hints();
412 dlg->deleteLater();
414 mEditor->applyHints( hints );
417 GuiElement *EditorWidget::selectElement( Editor::SelectionMode sm )
419 mInSelection = true;
420 mSelectionMode = sm;
421 mEventLoop->exec();
422 if( !mHoveredElement || !mActiveElement || mHoveredElement->properties()->group !=
423 mActiveElement->properties()->group )
424 mHoveredElement = 0;
425 return mHoveredElement;
428 #include "editorwidget.moc"