2 /***************************************************************************
3 * Copyright (C) 2005,2006,2007 by Siraj Razick *
6 * Translated to Ruby by Richard Dale *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with self program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
22 ***************************************************************************/
25 require 'plasma_applet'
26 require 'analog_clock_config'
27 require 'timezones_config'
33 class Main < ClockApplet
35 slots :moveSecondHand, :configAccepted,
36 'dataUpdated(QString, Plasma::DataEngine::Data)'
38 def initialize(parent, args = nil)
40 KDE::Global.locale.insertCatalog("libplasmaclock")
42 setHasConfigurationInterface(true)
44 setAspectRatioMode(Plasma::Square)
46 @theme = Plasma::Svg.new(self)
47 @theme.imagePath = "widgets/clock"
48 @theme.containsMultipleImages = false
52 @showTimeString = false
53 @showSecondHand = false
54 @ui = Ui::AnalogClockConfig.new
55 @calendarUi = Ui::Calendar.new
57 @lastTimeSeen = Qt::Time.new
64 @showTimeString = cg.readEntry("showTimeString", false)
65 @showSecondHand = cg.readEntry("showSecondHand", false)
66 @fancyHands = cg.readEntry("fancyHands", false)
67 self.currentTimezone = cg.readEntry("timezone", localTimezone())
73 # Use 'dataEngine("ruby-time")' for the ruby version of the engine
74 timeEngine = dataEngine("time")
76 timeEngine.connectSource(currentTimezone(), self, 500)
78 timeEngine.connectSource(currentTimezone(), self, 6000, Plasma::AlignToMinute)
82 def constraintsEvent(constraints)
83 if constraints.to_i & Plasma::FormFactorConstraint.to_i
84 setBackgroundHints(NoBackground)
87 if constraints.to_i & Plasma::SizeConstraint.to_i
93 if @theme.hasElement("hint-square-clock")
97 path = Qt::PainterPath.new
98 path.addEllipse(boundingRect().adjusted(-2, -2, 2, 2))
102 def dataUpdated(source, data)
103 @time = data["Time"].toTime()
104 if @time.minute == @lastTimeSeen.minute &&
105 @time.second == @lastTimeSeen.second
106 # avoid unnecessary repaints
110 if @secondHandUpdateTimer
111 @secondHandUpdateTimer.stop
114 @lastTimeSeen = @time
118 def createClockConfigurationInterface(parent)
119 # TODO: Make the size settable
120 widget = Qt::Widget.new
122 parent.addPage(widget, KDE.i18n("General"), icon)
124 @ui.showTimeStringCheckBox.checked = @showTimeString
125 @ui.showSecondHandCheckBox.checked = @showSecondHand
128 def clockConfigAccepted()
130 @showTimeString = @ui.showTimeStringCheckBox.checked?
131 @showSecondHand = @ui.showSecondHandCheckBox.checked?
133 cg.writeEntry("showTimeString", @showTimeString)
134 cg.writeEntry("showSecondHand", @showSecondHand)
137 dataEngine("time").disconnectSource(currentTimezone(), self)
140 constraintsEvent(Plasma::AllConstraints)
141 emit configNeedsSaving
144 def changeEngineTimezone(oldTimezone, newTimezone)
145 dataEngine("time").disconnectSource(oldTimezone, self)
146 timeEngine = dataEngine("time")
148 timeEngine.connectSource(newTimezone, self, 500)
150 timeEngine.connectSource(newTimezone, self, 6000, Plasma::AlignToMinute)
158 def drawHand(p, rotation, handName)
160 boundSize = boundingRect.size
161 elementRect = @theme.elementRect(handName)
163 p.translate(boundSize.width() / 2, boundSize.height() / 2)
165 p.translate(-elementRect.width / 2, -(@theme.elementRect("clockFace").center.y - elementRect.top))
166 @theme.paint(p, Qt::RectF.new(Qt::PointF.new(0.0, 0.0), elementRect.size), handName)
171 def paintInterface(p, option, rect)
172 tempRect = Qt::RectF.new(0, 0, 0, 0)
174 boundSize = geometry.size
176 p.renderHint = Qt::Painter::SmoothPixmapTransform
178 minutes = 6.0 * @time.minute - 180
179 hours = 30.0 * @time.hour - 180 + ((@time.minute / 59.0) * 30.0)
181 @theme.paint(p, Qt::RectF.new(rect), "ClockFace")
184 fm = Qt::FontMetrics.new(Qt::Application.font)
187 # FIXME: temporary time output
188 time = @time.toString
190 time = @time.toString("hh:mm")
193 textRect = Qt::Rect.new((rect.width/2 - fm.width(time) / 2),((rect.height / 2) - fm.xHeight * 4),
194 fm.width(time), fm.xHeight())
197 background = Plasma::Theme.defaultTheme.color(Plasma::Theme::BackgroundColor)
198 background.setAlphaF(0.5)
199 p.brush = Qt::Brush.new(background)
201 p.setRenderHint(Qt::Painter::Antialiasing, true)
202 p.drawPath(Plasma::PaintUtils.roundedRectangle(Qt::RectF.new(textRect.adjusted(-margin, -margin, margin, margin)), margin))
203 p.setRenderHint(Qt::Painter::Antialiasing, false)
205 p.pen = Plasma::Theme::defaultTheme.color(Plasma::Theme::TextColor)
207 p.drawText(textRect.bottomLeft, time)
210 # Make sure we paint the second hand on top of the others
213 seconds = anglePerSec * @time.second() - 180
216 if @secondHandUpdateTimer.nil?
217 @secondHandUpdateTimer = Qt::Timer.new(self)
218 connect(@secondHandUpdateTimer, SIGNAL(:timeout), self, SLOT(:moveSecondHand))
221 if !@secondHandUpdateTimer.active?
222 @secondHandUpdateTimer.start(50)
223 @animationStart = Qt::Time.currentTime.msec
227 b = 1.0 # Drag coefficient
228 k = 1.5 # Spring constant
229 gamma = b / (2 * m) # Dampening constant
230 omega0 = Math.sqrt(k / m)
231 omega1 = Math.sqrt(omega0 * omega0 - gamma * gamma)
232 elapsed = Qt::Time.currentTime().msec() - @animationStart
233 t = (4 * Math::PI) * (elapsed / runTime)
234 val = 1 + exp(-gamma * t) * -Math.cos(omega1 * t)
237 @secondHandUpdateTimer.stop
239 seconds += -anglePerSec + (anglePerSec * val)
245 if @theme.hasElement("HourHandShadow")
248 drawHand(p, hours, "HourHandShadow")
249 drawHand(p, minutes, "MinuteHandShadow")
252 drawHand(p, seconds, "SecondHandShadow")
258 drawHand(p, hours, "HourHand")
259 drawHand(p, minutes, "MinuteHand")
261 drawHand(p, seconds, "SecondHand")
265 @theme.resize(boundSize)
266 elementSize = Qt::SizeF.new(@theme.elementSize("HandCenterScrew"))
267 tempRect.size = elementSize
268 p.translate(boundSize.width / 2.0 - elementSize.width / 2.0, boundSize.height / 2.0 - elementSize.height / 2.0)
269 @theme.paint(p, tempRect, "HandCenterScrew")
272 @theme.paint(p, Qt::RectF.new(rect), "Glass")