1
by Carsten Pfeiffer
import of KRuler for Till |
1 |
/***************************************************************************
|
2 |
klineal.cpp - description
|
|
3 |
-------------------
|
|
271
by Arto Hytönen
This commit fixes Krazy issue 12 on kdegraphics/kruler. |
4 |
Begin : Fri Oct 13 2000
|
338
by Mathias Soeken
coding style. some cleanup |
5 |
Copyright : 2000 by Till Krech <till@snafu.de>
|
6 |
2008 by Mathias Soeken <msoeken@informatik.uni-bremen.de>
|
|
534.1.22
by Aurélien Gâteau
Add copyright |
7 |
2017 by Aurélien Gâteau <agateau@kde.org>
|
1
by Carsten Pfeiffer
import of KRuler for Till |
8 |
***************************************************************************/
|
9 |
||
10 |
/***************************************************************************
|
|
11 |
* *
|
|
12 |
* This program is free software; you can redistribute it and/or modify *
|
|
13 |
* it under the terms of the GNU General Public License as published by *
|
|
14 |
* the Free Software Foundation; either version 2 of the License, or *
|
|
15 |
* (at your option) any later version. *
|
|
16 |
* *
|
|
17 |
***************************************************************************/
|
|
18 |
||
257
by Pino Toscano
own header first |
19 |
#include "klineal.h" |
20 |
||
486.1.1
by Christoph Feck
Port KRuler to KF5 |
21 |
#include <QAction> |
22 |
#include <QApplication> |
|
269
by Pino Toscano
use QLinearGradient instead of KImageEffect::gradient() |
23 |
#include <QBrush> |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
24 |
#include <QDesktopWidget> |
25 |
#include <QInputDialog> |
|
26 |
#include <QMenu> |
|
27 |
#include <QMouseEvent> |
|
237
by Urs Wolfer
* deprecated-- |
28 |
#include <QPainter> |
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
29 |
#include <QSlider> |
30 |
#include <QWidgetAction> |
|
119
by Andreas Simon
- s/iostream.h/iostream |
31 |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
32 |
#include <KAboutData> |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
33 |
#include <KActionCollection> |
331
by Mathias Soeken
Make use of KStandardAction |
34 |
#include <KConfig> |
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
35 |
#include <KConfigDialog> |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
36 |
#include <KHelpClient> |
332
by Mathias Soeken
fix includes |
37 |
#include <KHelpMenu> |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
38 |
#include <KLocalizedString> |
331
by Mathias Soeken
Make use of KStandardAction |
39 |
#include <KNotification> |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
40 |
#include <KShortcutsDialog> |
330
by Mathias Soeken
Make use of KStandardAction |
41 |
#include <KStandardAction> |
332
by Mathias Soeken
fix includes |
42 |
#include <KWindowSystem> |
1
by Carsten Pfeiffer
import of KRuler for Till |
43 |
|
486.1.5
by Christoph Feck
Port native window moving to XCB |
44 |
#include "krulerconfig.h" |
45 |
||
46 |
#ifdef KRULER_HAVE_X11
|
|
47 |
#include <QX11Info> |
|
370
by Mathias Soeken
There is now an advanced option which enables moving the window by using NETRootInfo::moveResizeRequest, |
48 |
#include <netwm.h> |
486.1.5
by Christoph Feck
Port native window moving to XCB |
49 |
#endif
|
370
by Mathias Soeken
There is now an advanced option which enables moving the window by using NETRootInfo::moveResizeRequest, |
50 |
|
344
by Mathias Soeken
Use KConfig XT instead of hard coded KConfig calls |
51 |
#include "kruler.h" |
378
by Laurent Montel
Add preference in systemtray menu |
52 |
#include "krulersystemtray.h" |
339
by Mathias Soeken
This fixes some clipping bugs with the two labels. |
53 |
|
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
54 |
#include "ui_cfg_appearance.h" |
370
by Mathias Soeken
There is now an advanced option which enables moving the window by using NETRootInfo::moveResizeRequest, |
55 |
#include "ui_cfg_advanced.h" |
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
56 |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
57 |
static const int RESIZE_HANDLE_LENGTH = 7; |
58 |
static const int RESIZE_HANDLE_THICKNESS = 24; |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
59 |
static const qreal RESIZE_HANDLE_OPACITY = 0.3; |
1
by Carsten Pfeiffer
import of KRuler for Till |
60 |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
61 |
static const int SMALL_TICK_SIZE = 6; |
62 |
static const int MEDIUM1_TICK_SIZE = 10; |
|
63 |
static const int MEDIUM2_TICK_SIZE = 15; |
|
64 |
static const int LARGE_TICK_SIZE = 18; |
|
534.1.17
by Aurélien Gâteau
Make ticks not fully opaque |
65 |
static const qreal TICK_OPACITY = 0.3; |
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
66 |
|
67 |
static const int THICKNESS = 70; |
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
68 |
|
69 |
static const qreal OVERLAY_OPACITY = 0.1; |
|
70 |
static const qreal OVERLAY_BORDER_OPACITY = 0.3; |
|
71 |
||
72 |
static const int INDICATOR_MARGIN = 6; |
|
73 |
static const int INDICATOR_RECT_RADIUS = 3; |
|
74 |
static const qreal INDICATOR_RECT_OPACITY = 0.6; |
|
75 |
||
534.1.15
by Aurélien Gâteau
Use a red cross cursor |
76 |
static const int CURSOR_SIZE = 15; // Must be an odd number |
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
77 |
|
1
by Carsten Pfeiffer
import of KRuler for Till |
78 |
/**
|
335
by Mathias Soeken
some code cleanup |
79 |
* create the thingy with no borders and set up
|
80 |
* its members
|
|
81 |
*/
|
|
338
by Mathias Soeken
coding style. some cleanup |
82 |
KLineal::KLineal( QWidget *parent ) |
562
by Laurent Montel
USe nullptr + explicit + override |
83 |
: QWidget( parent ) |
335
by Mathias Soeken
some code cleanup |
84 |
{
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
85 |
setAttribute( Qt::WA_TranslucentBackground ); |
335
by Mathias Soeken
some code cleanup |
86 |
KWindowSystem::setType( winId(), NET::Override ); // or NET::Normal |
87 |
KWindowSystem::setState( winId(), NET::KeepAbove ); |
|
338
by Mathias Soeken
coding style. some cleanup |
88 |
|
458
by Alexander Potashev
Add message contexts "@title:window" to all window and dialog titles |
89 |
setWindowTitle( i18nc( "@title:window", "KRuler" ) ); |
363
by Mathias Soeken
This forces not to use a frame border. |
90 |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
91 |
setMinimumSize( THICKNESS, THICKNESS ); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
92 |
setMaximumSize( 8000, 8000 ); |
534.1.4
by Aurélien Gâteau
Remove color picker |
93 |
setWhatsThis( i18n( "This is a tool to measure pixel distances on the screen. " |
335
by Mathias Soeken
some code cleanup |
94 |
"It is useful for working on layouts of dialogs, web pages etc." ) ); |
95 |
setMouseTracking( true ); |
|
338
by Mathias Soeken
coding style. some cleanup |
96 |
|
344
by Mathias Soeken
Use KConfig XT instead of hard coded KConfig calls |
97 |
mColor = RulerSettings::self()->bgColor(); |
98 |
mScaleFont = RulerSettings::self()->scaleFont(); |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
99 |
int len = RulerSettings::self()->length(); |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
100 |
mHorizontal = RulerSettings::self()->horizontal(); |
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
101 |
mLeftToRight = RulerSettings::self()->leftToRight(); |
102 |
mOffset = RulerSettings::self()->offset(); |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
103 |
mRelativeScale = RulerSettings::self()->relativeScale(); |
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
104 |
mAlwaysOnTopLayer = RulerSettings::self()->alwaysOnTop(); |
1
by Carsten Pfeiffer
import of KRuler for Till |
105 |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
106 |
if ( mHorizontal ) { |
107 |
resize( QSize( len, THICKNESS ) ); |
|
108 |
} else { |
|
109 |
resize( QSize( THICKNESS, len ) ); |
|
110 |
}
|
|
335
by Mathias Soeken
some code cleanup |
111 |
|
534.1.15
by Aurélien Gâteau
Use a red cross cursor |
112 |
createCrossCursor(); |
113 |
||
365
by Mathias Soeken
Add buttons to rotate the ruler (turn left, turn right). The buttons are only visible when hovering over |
114 |
//BEGIN setup menu and actions
|
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
115 |
mActionCollection = new KActionCollection( this ); |
503
by Montel Laurent
Use new connect api + QStringLiteral |
116 |
mActionCollection->setConfigGroup( QStringLiteral( "Actions" ) ); |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
117 |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
118 |
mMenu = new QMenu( this ); |
534.1.6
by Aurélien Gâteau
Keep only one orientation action: Rotate |
119 |
addAction( mMenu, QIcon::fromTheme( QStringLiteral( "object-rotate-left" ) ), i18n( "Rotate" ), |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
120 |
this, SLOT(rotate()), Qt::Key_R, QStringLiteral( "turn_right" ) ); |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
121 |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
122 |
QMenu* scaleMenu = new QMenu( i18n( "&Scale" ), this ); |
123 |
mScaleDirectionAction = addAction( scaleMenu, QIcon(), i18n( "Right to Left" ), |
|
503
by Montel Laurent
Use new connect api + QStringLiteral |
124 |
this, SLOT(switchDirection()), Qt::Key_D, QStringLiteral( "right_to_left" ) ); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
125 |
mCenterOriginAction = addAction( scaleMenu, QIcon(), i18n( "Center Origin" ), |
503
by Montel Laurent
Use new connect api + QStringLiteral |
126 |
this, SLOT(centerOrigin()), Qt::Key_C, QStringLiteral( "center_origin" ) ); |
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
127 |
mCenterOriginAction->setEnabled( !mRelativeScale ); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
128 |
mOffsetAction = addAction( scaleMenu, QIcon(), i18n( "Offset..." ), |
503
by Montel Laurent
Use new connect api + QStringLiteral |
129 |
this, SLOT(slotOffset()), Qt::Key_O, QStringLiteral( "set_offset" ) ); |
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
130 |
mOffsetAction->setEnabled( !mRelativeScale ); |
131 |
scaleMenu->addSeparator(); |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
132 |
QAction *relativeScaleAction = addAction( scaleMenu, QIcon(), i18n( "Percentage" ), |
562
by Laurent Montel
USe nullptr + explicit + override |
133 |
nullptr, nullptr, QKeySequence(), QStringLiteral( "toggle_percentage" ) ); |
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
134 |
relativeScaleAction->setCheckable( true ); |
135 |
relativeScaleAction->setChecked( mRelativeScale ); |
|
486.1.2
by Montel Laurent
Port to new connect api. Port to reverse dns desktop |
136 |
connect(relativeScaleAction, &QAction::toggled, this, &KLineal::switchRelativeScale); |
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
137 |
mMenu->addMenu( scaleMenu ); |
344
by Mathias Soeken
Use KConfig XT instead of hard coded KConfig calls |
138 |
|
364
by Mathias Soeken
With Qt 4.5 we can create real ARGB translucent widgets. Now kruler can be made transparent, but with |
139 |
mOpacity = RulerSettings::self()->opacity(); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
140 |
QMenu* opacityMenu = new QMenu( i18n( "O&pacity" ), this ); |
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
141 |
QWidgetAction *opacityAction = new QWidgetAction( this ); |
142 |
QSlider *slider = new QSlider( this ); |
|
547
by Aurélien Gâteau
Improve opacity handling |
143 |
slider->setMinimum( 30 ); |
364
by Mathias Soeken
With Qt 4.5 we can create real ARGB translucent widgets. Now kruler can be made transparent, but with |
144 |
slider->setMaximum( 255 ); |
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
145 |
slider->setSingleStep( 1 ); |
146 |
slider->setOrientation( Qt::Horizontal ); |
|
364
by Mathias Soeken
With Qt 4.5 we can create real ARGB translucent widgets. Now kruler can be made transparent, but with |
147 |
slider->setValue( RulerSettings::self()->opacity() ); |
547
by Aurélien Gâteau
Improve opacity handling |
148 |
// Show ticks so that the slider is a bit taller, thus easier to grab
|
149 |
slider->setTickPosition( QSlider::TicksBothSides ); |
|
150 |
slider->setTickInterval( 30 ); |
|
486.1.2
by Montel Laurent
Port to new connect api. Port to reverse dns desktop |
151 |
connect(slider, &QSlider::valueChanged, this, &KLineal::slotOpacity); |
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
152 |
opacityAction->setDefaultWidget( slider ); |
153 |
opacityMenu->addAction( opacityAction ); |
|
154 |
mMenu->addMenu( opacityMenu ); |
|
155 |
||
486.1.7
by Christoph Feck
Fix warnings about renamed actions |
156 |
QAction *keyBindings = mActionCollection->addAction( KStandardAction::KeyBindings, this, SLOT(slotKeyBindings()) ); |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
157 |
mMenu->addAction( keyBindings ); |
486.1.7
by Christoph Feck
Fix warnings about renamed actions |
158 |
QAction *preferences = mActionCollection->addAction( KStandardAction::Preferences, this, SLOT(slotPreferences()) ); |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
159 |
mMenu->addAction( preferences ); |
351
by Mathias Soeken
Copy color under cursor with Ctrl+C (standard Copy shortcut) |
160 |
mMenu->addSeparator(); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
161 |
mMenu->addMenu( ( new KHelpMenu( this, KAboutData::applicationData(), true ) )->menu() ); |
335
by Mathias Soeken
some code cleanup |
162 |
mMenu->addSeparator(); |
358
by Mathias Soeken
Tray Icon for kruler. But it is configurable and hidden by default. |
163 |
if ( RulerSettings::self()->trayIcon() ) { |
373
by Laurent Montel
Fix show/hide close button when we show/hide systemtray |
164 |
createSystemTray(); |
165 |
}
|
|
166 |
||
486.1.7
by Christoph Feck
Fix warnings about renamed actions |
167 |
QAction *quit = mActionCollection->addAction( KStandardAction::Quit, qApp, SLOT(quit()) ); |
373
by Laurent Montel
Fix show/hide close button when we show/hide systemtray |
168 |
mMenu->addAction( quit ); |
169 |
||
170 |
mActionCollection->associateWidget( this ); |
|
171 |
mActionCollection->readSettings(); |
|
172 |
||
173 |
mLastClickPos = geometry().topLeft() + QPoint( width() / 2, height() / 2 ); |
|
174 |
||
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
175 |
setWindowFlags( mAlwaysOnTopLayer ? Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint |
176 |
: Qt::FramelessWindowHint ); |
|
177 |
||
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
178 |
setHorizontal( mHorizontal ); |
373
by Laurent Montel
Fix show/hide close button when we show/hide systemtray |
179 |
}
|
180 |
||
181 |
KLineal::~KLineal() |
|
182 |
{
|
|
398
by Mathias Soeken
* Fix indention |
183 |
delete mTrayIcon; |
373
by Laurent Montel
Fix show/hide close button when we show/hide systemtray |
184 |
}
|
185 |
||
534.1.15
by Aurélien Gâteau
Use a red cross cursor |
186 |
void KLineal::createCrossCursor() |
187 |
{
|
|
188 |
QPixmap pix( CURSOR_SIZE, CURSOR_SIZE ); |
|
189 |
int halfSize = CURSOR_SIZE / 2; |
|
190 |
{
|
|
191 |
pix.fill( Qt::transparent ); |
|
192 |
QPainter painter( &pix ); |
|
193 |
painter.setPen( Qt::red ); |
|
194 |
painter.drawLine( 0, halfSize, CURSOR_SIZE - 1, halfSize ); |
|
195 |
painter.drawLine( halfSize, 0, halfSize, CURSOR_SIZE - 1 ); |
|
196 |
}
|
|
197 |
mCrossCursor = QCursor( pix, halfSize, halfSize ); |
|
198 |
}
|
|
199 |
||
373
by Laurent Montel
Fix show/hide close button when we show/hide systemtray |
200 |
void KLineal::createSystemTray() |
201 |
{
|
|
534.1.7
by Aurélien Gâteau
Remove buttons |
202 |
mCloseAction = mActionCollection->addAction( KStandardAction::Close, this, SLOT(slotClose()) ); |
203 |
mMenu->addAction( mCloseAction ); |
|
444
by Laurent Montel
Fix compile with "DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII" |
204 |
|
398
by Mathias Soeken
* Fix indention |
205 |
if ( !mTrayIcon ) { |
503
by Montel Laurent
Use new connect api + QStringLiteral |
206 |
mTrayIcon = new KRulerSystemTray( QStringLiteral( "kruler" ), this, mActionCollection ); |
406
by Aurélien Gâteau
notification -> statusnotifier |
207 |
mTrayIcon->setCategory( KStatusNotifierItem::ApplicationStatus ); |
398
by Mathias Soeken
* Fix indention |
208 |
}
|
1
by Carsten Pfeiffer
import of KRuler for Till |
209 |
}
|
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
210 |
|
1
by Carsten Pfeiffer
import of KRuler for Till |
211 |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
212 |
QAction* KLineal::addAction( QMenu *menu, const QIcon& icon, const QString& text, |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
213 |
const QObject* receiver, const char* member, |
214 |
const QKeySequence &shortcut, const QString& name ) |
|
215 |
{
|
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
216 |
QAction *action = new QAction( icon, text, mActionCollection ); |
217 |
mActionCollection->setDefaultShortcut( action, shortcut ); |
|
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
218 |
if ( receiver ) { |
465
by Montel Laurent
Normalize |
219 |
connect( action, SIGNAL(triggered()), receiver, member ); |
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
220 |
}
|
221 |
menu->addAction( action ); |
|
222 |
mActionCollection->addAction( name, action ); |
|
223 |
return action; |
|
224 |
}
|
|
225 |
||
358
by Mathias Soeken
Tray Icon for kruler. But it is configurable and hidden by default. |
226 |
void KLineal::slotClose() |
227 |
{
|
|
228 |
hide(); |
|
229 |
}
|
|
230 |
||
310
by Laurent Montel
Fix use shortcut. |
231 |
void KLineal::slotQuit() |
232 |
{
|
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
233 |
qApp->quit(); |
310
by Laurent Montel
Fix use shortcut. |
234 |
}
|
235 |
||
338
by Mathias Soeken
coding style. some cleanup |
236 |
void KLineal::move( int x, int y ) |
237 |
{
|
|
238 |
move( QPoint( x, y ) ); |
|
239 |
}
|
|
240 |
||
241 |
void KLineal::move(const QPoint &p) |
|
242 |
{
|
|
243 |
setGeometry( QRect( p, size() ) ); |
|
244 |
}
|
|
245 |
||
379
by Laurent Montel
const'ify |
246 |
QPoint KLineal::pos() const |
338
by Mathias Soeken
coding style. some cleanup |
247 |
{
|
248 |
return frameGeometry().topLeft(); |
|
249 |
}
|
|
250 |
||
379
by Laurent Montel
const'ify |
251 |
int KLineal::x() const |
338
by Mathias Soeken
coding style. some cleanup |
252 |
{
|
1
by Carsten Pfeiffer
import of KRuler for Till |
253 |
return pos().x(); |
254 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
255 |
|
379
by Laurent Montel
const'ify |
256 |
int KLineal::y() const |
338
by Mathias Soeken
coding style. some cleanup |
257 |
{
|
1
by Carsten Pfeiffer
import of KRuler for Till |
258 |
return pos().y(); |
259 |
}
|
|
260 |
||
338
by Mathias Soeken
coding style. some cleanup |
261 |
void KLineal::drawBackground( QPainter& painter ) |
262 |
{
|
|
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
263 |
QColor a, b, bg = mColor; |
269
by Pino Toscano
use QLinearGradient instead of KImageEffect::gradient() |
264 |
QLinearGradient gradient; |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
265 |
if ( mHorizontal ) { |
571
by Laurent Montel
Make it compile with qt5.13 |
266 |
a = bg.lighter( 120 ); |
267 |
b = bg.darker( 130 ); |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
268 |
gradient = QLinearGradient( 1, 0, 1, height() ); |
269 |
} else { |
|
571
by Laurent Montel
Make it compile with qt5.13 |
270 |
a = bg.lighter( 120 ); |
271 |
b = bg.darker( 130 ); |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
272 |
gradient = QLinearGradient( 0, 1, width(), 1 ); |
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
273 |
}
|
364
by Mathias Soeken
With Qt 4.5 we can create real ARGB translucent widgets. Now kruler can be made transparent, but with |
274 |
a.setAlpha( mOpacity ); |
275 |
b.setAlpha( mOpacity ); |
|
338
by Mathias Soeken
coding style. some cleanup |
276 |
gradient.setColorAt( 0, a ); |
277 |
gradient.setColorAt( 1, b ); |
|
278 |
painter.fillRect( rect(), QBrush( gradient ) ); |
|
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
279 |
}
|
280 |
||
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
281 |
void KLineal::setHorizontal( bool horizontal ) |
338
by Mathias Soeken
coding style. some cleanup |
282 |
{
|
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
283 |
QRect r = frameGeometry(); |
534.1.13
by Aurélien Gâteau
Remove length actions |
284 |
if ( mHorizontal != horizontal ) { |
285 |
r.setSize( r.size().transposed() ); |
|
286 |
}
|
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
287 |
mHorizontal = horizontal; |
288 |
QPoint center = mLastClickPos; |
|
162
by Laurent Montel
Deprecated-- |
289 |
|
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
290 |
if ( mClicked ) { |
132
by Ryan Cumming
Fix an error found by valgrind |
291 |
center = mLastClickPos; |
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
292 |
mClicked = false; |
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
293 |
} else { |
294 |
center = r.topLeft() + QPoint( width() / 2, height() / 2 ); |
|
295 |
}
|
|
237
by Urs Wolfer
* deprecated-- |
296 |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
297 |
QPoint newTopLeft = QPoint( center.x() - height() / 2, center.y() - width() / 2 ); |
329
by Mathias Soeken
Fix "Window moves when changing orientation" |
298 |
r.moveTo(newTopLeft); |
190
by Waldo Bastian
Stay on screen when changing orientation. (BR83293) |
299 |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
300 |
QRect desktop = QApplication::desktop()->screenGeometry( this ); |
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
301 |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
302 |
if ( r.width() > desktop.width() ) { |
303 |
r.setWidth( desktop.width() ); |
|
304 |
}
|
|
305 |
||
306 |
if ( r.height() > desktop.height() ) { |
|
307 |
r.setHeight( desktop.height() ); |
|
308 |
}
|
|
309 |
||
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
310 |
if ( r.top() < desktop.top() ) { |
338
by Mathias Soeken
coding style. some cleanup |
311 |
r.moveTop( desktop.top() ); |
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
312 |
}
|
313 |
||
314 |
if ( r.bottom() > desktop.bottom() ) { |
|
338
by Mathias Soeken
coding style. some cleanup |
315 |
r.moveBottom( desktop.bottom() ); |
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
316 |
}
|
317 |
||
318 |
if ( r.left() < desktop.left() ) { |
|
338
by Mathias Soeken
coding style. some cleanup |
319 |
r.moveLeft( desktop.left() ); |
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
320 |
}
|
321 |
||
322 |
if ( r.right() > desktop.right() ) { |
|
323 |
r.moveRight( desktop.right() ); |
|
324 |
}
|
|
325 |
||
326 |
setGeometry( r ); |
|
338
by Mathias Soeken
coding style. some cleanup |
327 |
|
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
328 |
updateScaleDirectionMenuItem(); |
329 |
||
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
330 |
saveSettings(); |
1
by Carsten Pfeiffer
import of KRuler for Till |
331 |
}
|
334
by Mathias Soeken
Set explicitely the size. Just rotating can cause errors |
332 |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
333 |
void KLineal::rotate() |
334 |
{
|
|
335 |
setHorizontal( !mHorizontal ); |
|
338
by Mathias Soeken
coding style. some cleanup |
336 |
}
|
337 |
||
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
338 |
void KLineal::updateScaleDirectionMenuItem() |
339 |
{
|
|
340 |
if ( !mScaleDirectionAction ) return; |
|
341 |
||
342 |
QString label; |
|
343 |
||
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
344 |
if ( mHorizontal ) { |
385
by Stephan Binner
i18n style guide fixes: http://techbase.kde.org/Projects/Usability/HIG/Capitalization |
345 |
label = mLeftToRight ? i18n( "Right to Left" ) : i18n( "Left to Right" ); |
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
346 |
} else { |
385
by Stephan Binner
i18n style guide fixes: http://techbase.kde.org/Projects/Usability/HIG/Capitalization |
347 |
label = mLeftToRight ? i18n( "Bottom to Top" ) : i18n( "Top to Bottom" ); |
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
348 |
}
|
349 |
||
350 |
mScaleDirectionAction->setText( label ); |
|
351 |
}
|
|
352 |
||
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
353 |
QRect KLineal::beginRect() const |
354 |
{
|
|
534.1.13
by Aurélien Gâteau
Remove length actions |
355 |
int shortLen = RESIZE_HANDLE_THICKNESS; |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
356 |
return mHorizontal |
534.1.13
by Aurélien Gâteau
Remove length actions |
357 |
? QRect( 0, ( height() - shortLen ) / 2 + 1, RESIZE_HANDLE_LENGTH, shortLen ) |
358 |
: QRect( ( width() - shortLen ) / 2, 0, shortLen, RESIZE_HANDLE_LENGTH ); |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
359 |
}
|
360 |
||
361 |
QRect KLineal::endRect() const |
|
362 |
{
|
|
534.1.13
by Aurélien Gâteau
Remove length actions |
363 |
int shortLen = RESIZE_HANDLE_THICKNESS; |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
364 |
return mHorizontal |
534.1.13
by Aurélien Gâteau
Remove length actions |
365 |
? QRect( width() - RESIZE_HANDLE_LENGTH, ( height() - shortLen ) / 2 + 1, RESIZE_HANDLE_LENGTH, shortLen ) |
366 |
: QRect( ( width() - shortLen ) / 2, height() - RESIZE_HANDLE_LENGTH, shortLen, RESIZE_HANDLE_LENGTH ); |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
367 |
}
|
368 |
||
369 |
Qt::CursorShape KLineal::resizeCursor() const |
|
370 |
{
|
|
371 |
return mHorizontal ? Qt::SizeHorCursor : Qt::SizeVerCursor; |
|
372 |
}
|
|
373 |
||
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
374 |
void KLineal::switchDirection() |
375 |
{
|
|
376 |
mLeftToRight = !mLeftToRight; |
|
377 |
updateScaleDirectionMenuItem(); |
|
378 |
repaint(); |
|
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
379 |
saveSettings(); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
380 |
}
|
381 |
||
382 |
void KLineal::centerOrigin() |
|
383 |
{
|
|
534.1.13
by Aurélien Gâteau
Remove length actions |
384 |
mOffset = -( length() / 2 ); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
385 |
repaint(); |
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
386 |
saveSettings(); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
387 |
}
|
388 |
||
389 |
void KLineal::slotOffset() |
|
390 |
{
|
|
391 |
bool ok; |
|
486.1.1
by Christoph Feck
Port KRuler to KF5 |
392 |
int newOffset = QInputDialog::getInt( this, i18nc( "@title:window", "Scale Offset" ), |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
393 |
i18n( "Offset:" ), mOffset, |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
394 |
-2147483647, 2147483647, 1, &ok ); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
395 |
|
396 |
if ( ok ) { |
|
397 |
mOffset = newOffset; |
|
398 |
repaint(); |
|
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
399 |
saveSettings(); |
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
400 |
}
|
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
401 |
}
|
402 |
||
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
403 |
void KLineal::slotOpacity( int value ) |
404 |
{
|
|
364
by Mathias Soeken
With Qt 4.5 we can create real ARGB translucent widgets. Now kruler can be made transparent, but with |
405 |
mOpacity = value; |
406 |
repaint(); |
|
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
407 |
RulerSettings::self()->setOpacity( value ); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
408 |
RulerSettings::self()->save(); |
359
by Mathias Soeken
kruler is now configurable to be (semi-)transparent. There is a new menu "Opacity" in the context menu |
409 |
}
|
410 |
||
362
by Mathias Soeken
Make all actions configurable via a KActionCollection and KShortcutsDialog |
411 |
void KLineal::slotKeyBindings() |
412 |
{
|
|
413 |
KShortcutsDialog::configure( mActionCollection ); |
|
414 |
}
|
|
415 |
||
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
416 |
void KLineal::slotPreferences() |
417 |
{
|
|
503
by Montel Laurent
Use new connect api + QStringLiteral |
418 |
KConfigDialog *dialog = new KConfigDialog( this, QStringLiteral( "settings" ), RulerSettings::self() ); |
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
419 |
|
420 |
Ui::ConfigAppearance appearanceConfig; |
|
421 |
QWidget *appearanceConfigWidget = new QWidget( dialog ); |
|
422 |
appearanceConfig.setupUi( appearanceConfigWidget ); |
|
503
by Montel Laurent
Use new connect api + QStringLiteral |
423 |
dialog->addPage( appearanceConfigWidget, i18n( "Appearance" ), QStringLiteral( "preferences-desktop-default-applications" ) ); |
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
424 |
|
489
by Christoph Feck
Fix build on non-X11 systems |
425 |
#ifdef KRULER_HAVE_X11
|
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
426 |
// Advanced page only contains the "Native moving" and "Always on top" settings, disable when not running on X11
|
488
by Christoph Feck
Add runtime checks for X11 platform |
427 |
if ( QX11Info::isPlatformX11() ) { |
428 |
Ui::ConfigAdvanced advancedConfig; |
|
429 |
QWidget *advancedConfigWidget = new QWidget( dialog ); |
|
430 |
advancedConfig.setupUi( advancedConfigWidget ); |
|
503
by Montel Laurent
Use new connect api + QStringLiteral |
431 |
dialog->addPage( advancedConfigWidget, i18n( "Advanced" ), QStringLiteral( "preferences-other" ) ); |
488
by Christoph Feck
Add runtime checks for X11 platform |
432 |
}
|
489
by Christoph Feck
Fix build on non-X11 systems |
433 |
#endif
|
370
by Mathias Soeken
There is now an advanced option which enables moving the window by using NETRootInfo::moveResizeRequest, |
434 |
|
486.1.2
by Montel Laurent
Port to new connect api. Port to reverse dns desktop |
435 |
connect(dialog, &KConfigDialog::settingsChanged, this, &KLineal::loadConfig); |
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
436 |
dialog->exec(); |
371
by Laurent Montel
Fix mem leak |
437 |
delete dialog; |
375
by Laurent Montel
Now make "apply" in config dialog works |
438 |
}
|
439 |
||
440 |
void KLineal::loadConfig() |
|
441 |
{
|
|
398
by Mathias Soeken
* Fix indention |
442 |
mColor = RulerSettings::self()->bgColor(); |
443 |
mScaleFont = RulerSettings::self()->scaleFont(); |
|
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
444 |
mAlwaysOnTopLayer = RulerSettings::self()->alwaysOnTop(); |
398
by Mathias Soeken
* Fix indention |
445 |
saveSettings(); |
446 |
||
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
447 |
setWindowFlags( mAlwaysOnTopLayer ? Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint |
448 |
: Qt::FramelessWindowHint ); |
|
449 |
||
398
by Mathias Soeken
* Fix indention |
450 |
if ( RulerSettings::self()->trayIcon() ) { |
451 |
if ( !mTrayIcon ) { |
|
452 |
createSystemTray(); |
|
453 |
}
|
|
454 |
} else { |
|
450
by Laurent Montel
Not necessary to check pointer |
455 |
delete mTrayIcon; |
562
by Laurent Montel
USe nullptr + explicit + override |
456 |
mTrayIcon = nullptr; |
398
by Mathias Soeken
* Fix indention |
457 |
|
458 |
if ( mCloseAction ) { |
|
459 |
mCloseAction->setVisible( false ); |
|
460 |
}
|
|
461 |
}
|
|
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
462 |
show(); |
398
by Mathias Soeken
* Fix indention |
463 |
repaint(); |
375
by Laurent Montel
Now make "apply" in config dialog works |
464 |
}
|
465 |
||
352
by Mathias Soeken
I moved the menu items for setting color and font to a new config dialog. There will come some more |
466 |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
467 |
void KLineal::switchRelativeScale( bool checked ) |
468 |
{
|
|
469 |
mRelativeScale = checked; |
|
470 |
||
471 |
mCenterOriginAction->setEnabled( !mRelativeScale ); |
|
472 |
mOffsetAction->setEnabled( !mRelativeScale ); |
|
473 |
||
474 |
repaint(); |
|
475 |
saveSettings(); |
|
476 |
}
|
|
477 |
||
14
by Till Krech
fixed color display truncation, added cursor keys to move one pixel (10 with shift), added sound event |
478 |
/**
|
338
by Mathias Soeken
coding style. some cleanup |
479 |
* save the ruler color to the config file
|
480 |
*/
|
|
481 |
void KLineal::saveSettings() |
|
482 |
{
|
|
344
by Mathias Soeken
Use KConfig XT instead of hard coded KConfig calls |
483 |
RulerSettings::self()->setBgColor( mColor ); |
484 |
RulerSettings::self()->setScaleFont( mScaleFont ); |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
485 |
RulerSettings::self()->setLength( length() ); |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
486 |
RulerSettings::self()->setHorizontal( mHorizontal ); |
348
by Mathias Soeken
Save 'Orientation', 'Offset' and 'Direction' and restore them at restart. |
487 |
RulerSettings::self()->setLeftToRight( mLeftToRight ); |
488 |
RulerSettings::self()->setOffset( mOffset ); |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
489 |
RulerSettings::self()->setRelativeScale( mRelativeScale ); |
508
by Alex Neundorf
-add option to stay "always on top" #317463 |
490 |
RulerSettings::self()->setAlwaysOnTop( mAlwaysOnTopLayer ); |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
491 |
RulerSettings::self()->save(); |
1
by Carsten Pfeiffer
import of KRuler for Till |
492 |
}
|
14
by Till Krech
fixed color display truncation, added cursor keys to move one pixel (10 with shift), added sound event |
493 |
|
1
by Carsten Pfeiffer
import of KRuler for Till |
494 |
/**
|
338
by Mathias Soeken
coding style. some cleanup |
495 |
* lets the context menu appear at current cursor position
|
496 |
*/
|
|
497 |
void KLineal::showMenu() |
|
498 |
{
|
|
237
by Urs Wolfer
* deprecated-- |
499 |
QPoint pos = QCursor::pos(); |
338
by Mathias Soeken
coding style. some cleanup |
500 |
mMenu->popup( pos ); |
501 |
}
|
|
502 |
||
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
503 |
bool KLineal::isResizing() const |
504 |
{
|
|
505 |
return mouseGrabber() == this && ( mRulerState == StateBegin || mRulerState == StateEnd ); |
|
506 |
}
|
|
507 |
||
534.1.13
by Aurélien Gâteau
Remove length actions |
508 |
int KLineal::length() const |
509 |
{
|
|
510 |
return mHorizontal ? width() : height(); |
|
511 |
}
|
|
512 |
||
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
513 |
QPoint KLineal::localCursorPos() const |
514 |
{
|
|
515 |
// For some reason mapFromGlobal( QCursor::pos() ) thinks the ruler is at 0, 0 at startup.
|
|
516 |
// compute the position ourselves to avoid that.
|
|
517 |
return QCursor::pos() - pos(); |
|
518 |
}
|
|
519 |
||
534.1.16
by Aurélien Gâteau
Add indicator overlay |
520 |
QString KLineal::indicatorText() const |
338
by Mathias Soeken
coding style. some cleanup |
521 |
{
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
522 |
int xy = mHorizontal ? localCursorPos().x() : localCursorPos().y(); |
534.1.14
by Aurélien Gâteau
Remove display of ruler size |
523 |
if ( !mRelativeScale ) { |
534.1.16
by Aurélien Gâteau
Add indicator overlay |
524 |
int len = mLeftToRight ? xy + 1 : length() - xy; |
525 |
return i18n( "%1 px", len ); |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
526 |
} else { |
534.1.16
by Aurélien Gâteau
Add indicator overlay |
527 |
int len = ( xy * 100.f ) / length(); |
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
528 |
|
534.1.14
by Aurélien Gâteau
Remove display of ruler size |
529 |
if ( !mLeftToRight ) { |
530 |
len = 100 - len; |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
531 |
}
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
532 |
return i18n( "%1%", len ); |
1
by Carsten Pfeiffer
import of KRuler for Till |
533 |
}
|
534 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
535 |
|
536 |
void KLineal::keyPressEvent( QKeyEvent *e ) |
|
537 |
{
|
|
538 |
QPoint dist; |
|
539 |
||
540 |
switch ( e->key() ) { |
|
237
by Urs Wolfer
* deprecated-- |
541 |
case Qt::Key_F1: |
486.1.1
by Christoph Feck
Port KRuler to KF5 |
542 |
KHelpClient::invokeHelp(); |
338
by Mathias Soeken
coding style. some cleanup |
543 |
return; |
544 |
||
237
by Urs Wolfer
* deprecated-- |
545 |
case Qt::Key_Left: |
338
by Mathias Soeken
coding style. some cleanup |
546 |
dist.setX( -1 ); |
237
by Urs Wolfer
* deprecated-- |
547 |
break; |
338
by Mathias Soeken
coding style. some cleanup |
548 |
|
237
by Urs Wolfer
* deprecated-- |
549 |
case Qt::Key_Right: |
338
by Mathias Soeken
coding style. some cleanup |
550 |
dist.setX( 1 ); |
237
by Urs Wolfer
* deprecated-- |
551 |
break; |
338
by Mathias Soeken
coding style. some cleanup |
552 |
|
237
by Urs Wolfer
* deprecated-- |
553 |
case Qt::Key_Up: |
338
by Mathias Soeken
coding style. some cleanup |
554 |
dist.setY( -1 ); |
237
by Urs Wolfer
* deprecated-- |
555 |
break; |
338
by Mathias Soeken
coding style. some cleanup |
556 |
|
237
by Urs Wolfer
* deprecated-- |
557 |
case Qt::Key_Down: |
338
by Mathias Soeken
coding style. some cleanup |
558 |
dist.setY( 1 ); |
237
by Urs Wolfer
* deprecated-- |
559 |
break; |
338
by Mathias Soeken
coding style. some cleanup |
560 |
|
237
by Urs Wolfer
* deprecated-- |
561 |
default: |
562 |
QWidget::keyPressEvent(e); |
|
563 |
return; |
|
564 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
565 |
|
566 |
if ( e->modifiers() & Qt::ShiftModifier ) { |
|
237
by Urs Wolfer
* deprecated-- |
567 |
dist *= 10; |
14
by Till Krech
fixed color display truncation, added cursor keys to move one pixel (10 with shift), added sound event |
568 |
}
|
338
by Mathias Soeken
coding style. some cleanup |
569 |
|
536.1.1
by Aurélien Gâteau
Use alt+arrow keys to move the mouse cursor |
570 |
if ( e->modifiers() & Qt::AltModifier ) { |
571 |
QCursor::setPos( QCursor::pos() + dist ); |
|
572 |
} else { |
|
573 |
move( pos() + dist ); |
|
574 |
update(); |
|
575 |
}
|
|
503
by Montel Laurent
Use new connect api + QStringLiteral |
576 |
KNotification::event( QString(), QStringLiteral( "cursormove" ), QString() ); |
14
by Till Krech
fixed color display truncation, added cursor keys to move one pixel (10 with shift), added sound event |
577 |
}
|
338
by Mathias Soeken
coding style. some cleanup |
578 |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
579 |
void KLineal::leaveEvent( QEvent *e ) |
580 |
{
|
|
581 |
Q_UNUSED( e ); |
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
582 |
update(); |
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
583 |
}
|
584 |
||
338
by Mathias Soeken
coding style. some cleanup |
585 |
void KLineal::mouseMoveEvent( QMouseEvent *inEvent ) |
586 |
{
|
|
587 |
Q_UNUSED( inEvent ); |
|
588 |
||
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
589 |
if ( mRulerState >= StateMove ) { |
590 |
if ( mouseGrabber() != this ) { |
|
591 |
return; |
|
592 |
}
|
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
593 |
if ( mRulerState == StateMove ) { |
486.1.5
by Christoph Feck
Port native window moving to XCB |
594 |
move( QCursor::pos() - mDragOffset ); |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
595 |
} else if ( mRulerState == StateBegin ) { |
596 |
QRect r = geometry(); |
|
597 |
if ( mHorizontal ) { |
|
598 |
r.setLeft( QCursor::pos().x() - mDragOffset.x() ); |
|
599 |
} else { |
|
600 |
r.setTop( QCursor::pos().y() - mDragOffset.y() ); |
|
601 |
}
|
|
602 |
setGeometry( r ); |
|
603 |
} else if ( mRulerState == StateEnd ) { |
|
604 |
QPoint end = QCursor::pos() + mDragOffset - pos(); |
|
605 |
QSize size = mHorizontal |
|
606 |
? QSize( end.x(), height() ) |
|
607 |
: QSize( width(), end.y() ); |
|
608 |
resize( size ); |
|
486.1.5
by Christoph Feck
Port native window moving to XCB |
609 |
}
|
1
by Carsten Pfeiffer
import of KRuler for Till |
610 |
} else { |
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
611 |
QPoint cpos = localCursorPos(); |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
612 |
mRulerState = StateNone; |
613 |
if ( beginRect().contains( cpos ) || endRect().contains( cpos) ) { |
|
614 |
setCursor( resizeCursor() ); |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
615 |
} else { |
534.1.15
by Aurélien Gâteau
Use a red cross cursor |
616 |
setCursor( mCrossCursor ); |
1
by Carsten Pfeiffer
import of KRuler for Till |
617 |
}
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
618 |
update(); |
1
by Carsten Pfeiffer
import of KRuler for Till |
619 |
}
|
620 |
}
|
|
621 |
||
622 |
/**
|
|
338
by Mathias Soeken
coding style. some cleanup |
623 |
* overwritten for dragging and context menu
|
624 |
*/
|
|
625 |
void KLineal::mousePressEvent( QMouseEvent *inEvent ) |
|
626 |
{
|
|
1
by Carsten Pfeiffer
import of KRuler for Till |
627 |
mLastClickPos = QCursor::pos(); |
628 |
||
629 |
QRect gr = geometry(); |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
630 |
mDragOffset = mLastClickPos - gr.topLeft(); |
338
by Mathias Soeken
coding style. some cleanup |
631 |
if ( inEvent->button() == Qt::LeftButton ) { |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
632 |
if ( mRulerState < StateMove ) { |
633 |
if ( beginRect().contains( mDragOffset ) ) { |
|
634 |
mRulerState = StateBegin; |
|
635 |
grabMouse( resizeCursor() ); |
|
636 |
} else if ( endRect().contains( mDragOffset ) ) { |
|
637 |
mDragOffset = gr.bottomRight() - mLastClickPos; |
|
638 |
mRulerState = StateEnd; |
|
639 |
grabMouse( resizeCursor() ); |
|
640 |
} else { |
|
641 |
if ( nativeMove() ) { |
|
642 |
startNativeMove( inEvent ); |
|
643 |
} else { |
|
644 |
mRulerState = StateMove; |
|
645 |
grabMouse( Qt::SizeAllCursor ); |
|
646 |
}
|
|
370
by Mathias Soeken
There is now an advanced option which enables moving the window by using NETRootInfo::moveResizeRequest, |
647 |
}
|
1
by Carsten Pfeiffer
import of KRuler for Till |
648 |
}
|
338
by Mathias Soeken
coding style. some cleanup |
649 |
} else if ( inEvent->button() == Qt::MidButton ) { |
346
by Mathias Soeken
kruler can now measure from right to left or from bottom to top, when orientation is north/south or west/east, respectively. |
650 |
mClicked = true; |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
651 |
rotate(); |
338
by Mathias Soeken
coding style. some cleanup |
652 |
} else if ( inEvent->button() == Qt::RightButton ) { |
1
by Carsten Pfeiffer
import of KRuler for Till |
653 |
showMenu(); |
654 |
}
|
|
655 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
656 |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
657 |
#ifdef KRULER_HAVE_X11
|
658 |
bool KLineal::nativeMove() const |
|
659 |
{
|
|
660 |
return QX11Info::isPlatformX11() && RulerSettings::self()->nativeMoving(); |
|
661 |
}
|
|
662 |
||
663 |
void KLineal::startNativeMove( QMouseEvent *inEvent ) |
|
664 |
{
|
|
665 |
xcb_ungrab_pointer( QX11Info::connection(), QX11Info::appTime() ); |
|
666 |
NETRootInfo wm_root( QX11Info::connection(), NET::WMMoveResize ); |
|
667 |
wm_root.moveResizeRequest( winId(), inEvent->globalX(), inEvent->globalY(), NET::Move ); |
|
668 |
}
|
|
669 |
||
670 |
void KLineal::stopNativeMove( QMouseEvent *inEvent ) |
|
671 |
{
|
|
672 |
NETRootInfo wm_root( QX11Info::connection(), NET::WMMoveResize ); |
|
673 |
wm_root.moveResizeRequest( winId(), inEvent->globalX(), inEvent->globalY(), NET::MoveResizeCancel ); |
|
674 |
}
|
|
675 |
#else
|
|
676 |
bool KLineal::nativeMove() const |
|
677 |
{
|
|
678 |
return false; |
|
679 |
}
|
|
680 |
||
681 |
void KLineal::startNativeMove( QMouseEvent *inEvent ) |
|
682 |
{
|
|
683 |
Q_UNUSED( inEvent ); |
|
684 |
}
|
|
685 |
||
686 |
void KLineal::stopNativeMove( QMouseEvent *inEvent ) |
|
687 |
{
|
|
688 |
Q_UNUSED( inEvent ); |
|
689 |
}
|
|
690 |
#endif
|
|
691 |
||
1
by Carsten Pfeiffer
import of KRuler for Till |
692 |
/**
|
338
by Mathias Soeken
coding style. some cleanup |
693 |
* overwritten for dragging
|
694 |
*/
|
|
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
695 |
void KLineal::mouseReleaseEvent( QMouseEvent *inEvent ) |
338
by Mathias Soeken
coding style. some cleanup |
696 |
{
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
697 |
if ( mRulerState != StateNone ) { |
698 |
mRulerState = StateNone; |
|
699 |
releaseMouse(); |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
700 |
saveSettings(); |
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
701 |
} else if ( nativeMove() ) { |
702 |
stopNativeMove( inEvent ); |
|
1
by Carsten Pfeiffer
import of KRuler for Till |
703 |
}
|
704 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
705 |
|
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
706 |
void KLineal::wheelEvent( QWheelEvent *e ) |
707 |
{
|
|
581
by Laurent Montel
Make it compiles without deprecated method |
708 |
int numDegrees = e->angleDelta().y() / 8; |
360
by Mathias Soeken
Changing the offset via the mouse wheel is now possible when holding the left mouse button. |
709 |
int numSteps = numDegrees / 15; |
710 |
||
711 |
// changing offset
|
|
712 |
if ( e->buttons() == Qt::LeftButton ) { |
|
713 |
if ( !mRelativeScale ) { |
|
714 |
mOffset += numSteps; |
|
715 |
||
716 |
repaint(); |
|
717 |
saveSettings(); |
|
718 |
}
|
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
719 |
}
|
720 |
||
721 |
QWidget::wheelEvent( e ); |
|
347
by Mathias Soeken
Now it is possible to change the origin of the scale. |
722 |
}
|
723 |
||
1
by Carsten Pfeiffer
import of KRuler for Till |
724 |
/**
|
338
by Mathias Soeken
coding style. some cleanup |
725 |
* draws the scale according to the orientation
|
726 |
*/
|
|
727 |
void KLineal::drawScale( QPainter &painter ) |
|
728 |
{
|
|
729 |
painter.setPen( Qt::black ); |
|
115
by Till Krech
Nicer look with gradient. Font selection. Border works again. Some tweaking with scale drawing to avoid overlapping text - if a reasonable font is chosen |
730 |
QFont font = mScaleFont; |
338
by Mathias Soeken
coding style. some cleanup |
731 |
painter.setFont( font ); |
534.1.16
by Aurélien Gâteau
Add indicator overlay |
732 |
int longLen = length(); |
338
by Mathias Soeken
coding style. some cleanup |
733 |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
734 |
if ( !mRelativeScale ) { |
735 |
int digit; |
|
736 |
int len; |
|
534.1.18
by Aurélien Gâteau
Fix missing ticks at ends of ruler |
737 |
// Draw from -1 to longLen rather than from 0 to longLen - 1 to take into
|
738 |
// account the offset applied in drawScaleTick
|
|
739 |
for ( int x = -1; x <= longLen; ++x ) { |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
740 |
if ( mLeftToRight ) { |
741 |
digit = x + mOffset; |
|
742 |
} else { |
|
743 |
digit = longLen - x + mOffset; |
|
744 |
}
|
|
745 |
||
746 |
if ( digit % 2 ) continue; |
|
747 |
||
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
748 |
if ( digit % 100 == 0 ) { |
749 |
len = LARGE_TICK_SIZE; |
|
750 |
} else if ( digit % 20 == 0 ) { |
|
751 |
len = MEDIUM2_TICK_SIZE; |
|
752 |
} else if (digit % 10 == 0) { |
|
753 |
len = MEDIUM1_TICK_SIZE; |
|
754 |
} else { |
|
755 |
len = SMALL_TICK_SIZE; |
|
756 |
}
|
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
757 |
|
534.1.10
by Aurélien Gâteau
Do not draw text under resize handles |
758 |
if ( digit % 100 == 0 && digit != 0 ) { |
581
by Laurent Montel
Make it compiles without deprecated method |
759 |
QString units = QStringLiteral("%1").arg(digit); |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
760 |
drawScaleText( painter, x, units ); |
761 |
}
|
|
762 |
||
763 |
drawScaleTick( painter, x, len ); |
|
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
764 |
}
|
765 |
} else { |
|
766 |
float step = longLen / 100.f; |
|
767 |
int len; |
|
768 |
||
769 |
for ( int i = 0; i <= 100; ++i ) { |
|
770 |
int x = (int)( i * step ); |
|
771 |
||
534.1.10
by Aurélien Gâteau
Do not draw text under resize handles |
772 |
if ( i % 10 == 0 && i != 0 && i != 100 ) { |
350
by Mathias Soeken
kruler is now able to handle relative scales (in both directions). If you have relative scales you can |
773 |
int value = mLeftToRight ? i : ( 100 - i ); |
581
by Laurent Montel
Make it compiles without deprecated method |
774 |
const QString units = QString::asprintf( "%d%%", value ); |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
775 |
drawScaleText( painter, x, units ); |
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
776 |
len = MEDIUM2_TICK_SIZE; |
777 |
} else { |
|
778 |
len = SMALL_TICK_SIZE; |
|
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
779 |
}
|
780 |
||
781 |
drawScaleTick( painter, x, len ); |
|
1
by Carsten Pfeiffer
import of KRuler for Till |
782 |
}
|
783 |
}
|
|
784 |
}
|
|
338
by Mathias Soeken
coding style. some cleanup |
785 |
|
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
786 |
void KLineal::drawScaleText( QPainter &painter, int x, const QString &text ) |
787 |
{
|
|
788 |
QFontMetrics metrics = painter.fontMetrics(); |
|
789 |
QSize textSize = metrics.size( Qt::TextSingleLine, text ); |
|
790 |
int w = width(); |
|
791 |
int h = height(); |
|
792 |
int tw = textSize.width(); |
|
793 |
int th = metrics.ascent(); |
|
794 |
||
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
795 |
if ( mHorizontal ) { |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
796 |
painter.drawText( x - tw / 2, (h + th) / 2, text ); |
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
797 |
} else { |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
798 |
painter.drawText( (w - tw) / 2, x + th / 2, text ); |
799 |
}
|
|
800 |
}
|
|
801 |
||
802 |
void KLineal::drawScaleTick( QPainter &painter, int x, int len ) |
|
803 |
{
|
|
534.1.17
by Aurélien Gâteau
Make ticks not fully opaque |
804 |
painter.setOpacity( TICK_OPACITY ); |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
805 |
int w = width(); |
806 |
int h = height(); |
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
807 |
// Offset by one because we are measuring lengths, not positions, so when the
|
534.1.12
by Aurélien Gâteau
Measure lengths, not positions |
808 |
// indicator is at position 0 it measures a length of 1 pixel.
|
534.1.16
by Aurélien Gâteau
Add indicator overlay |
809 |
if ( mLeftToRight ) { |
810 |
--x; |
|
811 |
} else { |
|
812 |
++x; |
|
813 |
}
|
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
814 |
if ( mHorizontal ) { |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
815 |
painter.drawLine( x, 0, x, len ); |
816 |
painter.drawLine( x, h, x, h - len ); |
|
534.1.8
by Aurélien Gâteau
Replace mOrientation with mHorizontal |
817 |
} else { |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
818 |
painter.drawLine( 0, x, len, x ); |
819 |
painter.drawLine( w, x, w - len, x ); |
|
820 |
}
|
|
534.1.17
by Aurélien Gâteau
Make ticks not fully opaque |
821 |
painter.setOpacity( 1 ); |
534.1.3
by Aurélien Gâteau
Factorize tick and text drawing code |
822 |
}
|
823 |
||
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
824 |
void KLineal::drawResizeHandle( QPainter &painter, Qt::Edge edge ) |
825 |
{
|
|
826 |
QRect rect; |
|
827 |
switch ( edge ) { |
|
828 |
case Qt::LeftEdge: |
|
829 |
case Qt::TopEdge: |
|
830 |
rect = beginRect(); |
|
831 |
break; |
|
832 |
case Qt::RightEdge: |
|
833 |
case Qt::BottomEdge: |
|
834 |
rect = endRect(); |
|
835 |
break; |
|
836 |
}
|
|
837 |
painter.setOpacity( RESIZE_HANDLE_OPACITY ); |
|
838 |
if ( mHorizontal ) { |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
839 |
int y1 = ( THICKNESS - RESIZE_HANDLE_THICKNESS ) / 2; |
840 |
int y2 = y1 + RESIZE_HANDLE_THICKNESS - 1; |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
841 |
for ( int x = rect.left() + 1; x < rect.right(); x += 2 ) { |
842 |
painter.drawLine( x, y1, x, y2 ); |
|
843 |
}
|
|
844 |
} else { |
|
534.1.13
by Aurélien Gâteau
Remove length actions |
845 |
int x1 = ( THICKNESS - RESIZE_HANDLE_THICKNESS ) / 2; |
846 |
int x2 = x1 + RESIZE_HANDLE_THICKNESS - 1; |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
847 |
for ( int y = rect.top() + 1; y < rect.bottom(); y += 2 ) { |
848 |
painter.drawLine( x1, y, x2, y ); |
|
849 |
}
|
|
850 |
}
|
|
851 |
painter.setOpacity( 1 ); |
|
852 |
}
|
|
853 |
||
534.1.16
by Aurélien Gâteau
Add indicator overlay |
854 |
void KLineal::drawIndicatorOverlay( QPainter &painter, int xy ) |
855 |
{
|
|
856 |
painter.setPen( Qt::red ); |
|
857 |
painter.setOpacity( OVERLAY_OPACITY ); |
|
858 |
if ( mHorizontal ) { |
|
859 |
QPointF p1( mLeftToRight ? 0 : width(), 0 ); |
|
860 |
QPointF p2( xy, THICKNESS ); |
|
861 |
QRectF rect( p1, p2 ); |
|
862 |
painter.fillRect( rect, Qt::red ); |
|
863 |
||
864 |
painter.setOpacity( OVERLAY_BORDER_OPACITY ); |
|
865 |
painter.drawLine( xy, 0, xy, THICKNESS ); |
|
866 |
} else { |
|
867 |
QPointF p1( 0, mLeftToRight ? 0 : height() ); |
|
868 |
QPointF p2( THICKNESS, xy ); |
|
869 |
QRectF rect( p1, p2 ); |
|
870 |
painter.fillRect( rect, Qt::red ); |
|
871 |
||
872 |
painter.setOpacity( OVERLAY_BORDER_OPACITY ); |
|
873 |
painter.drawLine( 0, xy, THICKNESS, xy ); |
|
874 |
}
|
|
875 |
}
|
|
876 |
||
877 |
void KLineal::drawIndicatorText( QPainter &painter, int xy ) |
|
878 |
{
|
|
879 |
QString text = indicatorText(); |
|
880 |
painter.setFont( font() ); |
|
881 |
QFontMetrics fm = QFontMetrics( font() ); |
|
882 |
int tx, ty; |
|
555
by Laurent Montel
fix compile without deprecated method |
883 |
int tw = fm.boundingRect(text).width(); |
534.1.16
by Aurélien Gâteau
Add indicator overlay |
884 |
if ( mHorizontal ) { |
885 |
tx = xy + INDICATOR_MARGIN; |
|
886 |
if ( tx + tw > width() ) { |
|
887 |
tx = xy - tw - INDICATOR_MARGIN; |
|
888 |
}
|
|
889 |
ty = height() - SMALL_TICK_SIZE - INDICATOR_RECT_RADIUS; |
|
890 |
} else { |
|
891 |
tx = ( width() - tw ) / 2; |
|
892 |
ty = xy + fm.ascent() + INDICATOR_MARGIN; |
|
893 |
if ( ty > height() ) { |
|
894 |
ty = xy - INDICATOR_MARGIN; |
|
895 |
}
|
|
896 |
}
|
|
897 |
||
898 |
// Draw background rect
|
|
899 |
painter.setRenderHint( QPainter::Antialiasing ); |
|
900 |
painter.setOpacity( INDICATOR_RECT_OPACITY ); |
|
901 |
painter.setBrush( Qt::red ); |
|
902 |
QRectF bgRect( tx, ty - fm.ascent() + 1, tw, fm.ascent() ); |
|
903 |
bgRect.adjust( -INDICATOR_RECT_RADIUS, -INDICATOR_RECT_RADIUS, INDICATOR_RECT_RADIUS, INDICATOR_RECT_RADIUS ); |
|
904 |
bgRect.translate( 0.5, 0.5 ); |
|
905 |
painter.drawRoundedRect( bgRect, INDICATOR_RECT_RADIUS, INDICATOR_RECT_RADIUS ); |
|
906 |
||
907 |
// Draw text
|
|
908 |
painter.setOpacity( 1 ); |
|
909 |
painter.setPen( Qt::white ); |
|
910 |
painter.drawText( tx, ty, text ); |
|
911 |
}
|
|
912 |
||
1
by Carsten Pfeiffer
import of KRuler for Till |
913 |
/**
|
338
by Mathias Soeken
coding style. some cleanup |
914 |
* actually draws the ruler
|
915 |
*/
|
|
916 |
void KLineal::paintEvent(QPaintEvent *inEvent ) |
|
917 |
{
|
|
918 |
Q_UNUSED( inEvent ); |
|
919 |
||
920 |
QPainter painter( this ); |
|
921 |
drawBackground( painter ); |
|
922 |
drawScale( painter ); |
|
534.1.9
by Aurélien Gâteau
Make edges resizeable by drag'n'drop |
923 |
|
924 |
drawResizeHandle( painter, mHorizontal ? Qt::LeftEdge : Qt::TopEdge ); |
|
925 |
drawResizeHandle( painter, mHorizontal ? Qt::RightEdge : Qt::BottomEdge ); |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
926 |
if ( underMouse() && !isResizing() ) { |
534.1.16
by Aurélien Gâteau
Add indicator overlay |
927 |
int xy = mHorizontal ? localCursorPos().x() : localCursorPos().y(); |
928 |
drawIndicatorOverlay( painter, xy ); |
|
929 |
drawIndicatorText( painter, xy ); |
|
534.1.11
by Aurélien Gâteau
Draw ruler indicator |
930 |
}
|
1
by Carsten Pfeiffer
import of KRuler for Till |
931 |
}
|