| Chris@58 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@0 | 2 | 
| Chris@0 | 3 /* | 
| Chris@59 | 4     Sonic Visualiser | 
| Chris@59 | 5     An audio file viewer and annotation editor. | 
| Chris@59 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@59 | 7     This file copyright 2006 Chris Cannam. | 
| Chris@0 | 8 | 
| Chris@59 | 9     This program is free software; you can redistribute it and/or | 
| Chris@59 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@59 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@59 | 12     License, or (at your option) any later version.  See the file | 
| Chris@59 | 13     COPYING included with this distribution for more information. | 
| Chris@0 | 14 */ | 
| Chris@0 | 15 | 
| Chris@0 | 16 #include "TimeRulerLayer.h" | 
| Chris@0 | 17 | 
| Chris@335 | 18 #include "LayerFactory.h" | 
| Chris@335 | 19 | 
| Chris@128 | 20 #include "data/model/Model.h" | 
| Chris@0 | 21 #include "base/RealTime.h" | 
| Chris@1345 | 22 #include "base/Preferences.h" | 
| Chris@1078 | 23 #include "view/View.h" | 
| Chris@1078 | 24 | 
| Chris@376 | 25 #include "ColourDatabase.h" | 
| Chris@1078 | 26 #include "PaintAssistant.h" | 
| Chris@0 | 27 | 
| Chris@0 | 28 #include <QPainter> | 
| Chris@0 | 29 | 
| Chris@0 | 30 #include <iostream> | 
| Chris@271 | 31 #include <cmath> | 
| Chris@1021 | 32 #include <stdexcept> | 
| Chris@0 | 33 | 
| Chris@1346 | 34 //#define DEBUG_TIME_RULER_LAYER 1 | 
| Chris@370 | 35 | 
| Chris@682 | 36 | 
| Chris@44 | 37 TimeRulerLayer::TimeRulerLayer() : | 
| Chris@287 | 38     SingleColourLayer(), | 
| Chris@0 | 39     m_model(0), | 
| Chris@0 | 40     m_labelHeight(LabelTop) | 
| Chris@0 | 41 { | 
| Chris@44 | 42 | 
| Chris@0 | 43 } | 
| Chris@0 | 44 | 
| Chris@0 | 45 void | 
| Chris@0 | 46 TimeRulerLayer::setModel(Model *model) | 
| Chris@0 | 47 { | 
| Chris@0 | 48     if (m_model == model) return; | 
| Chris@0 | 49     m_model = model; | 
| Chris@0 | 50     emit modelReplaced(); | 
| Chris@0 | 51 } | 
| Chris@0 | 52 | 
| Chris@271 | 53 bool | 
| Chris@918 | 54 TimeRulerLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 
| Chris@805 | 55                                    int &resolution, SnapType snap) const | 
| Chris@271 | 56 { | 
| Chris@271 | 57     if (!m_model) { | 
| Chris@271 | 58         resolution = 1; | 
| Chris@271 | 59         return false; | 
| Chris@271 | 60     } | 
| Chris@271 | 61 | 
| Chris@271 | 62     bool q; | 
| Chris@1346 | 63     int64_t tickUSec = getMajorTickUSec(v, q); | 
| Chris@1346 | 64     RealTime rtick = RealTime::fromMicroseconds(tickUSec); | 
| Chris@908 | 65     sv_samplerate_t rate = m_model->getSampleRate(); | 
| Chris@271 | 66 | 
| Chris@271 | 67     RealTime rt = RealTime::frame2RealTime(frame, rate); | 
| Chris@271 | 68     double ratio = rt / rtick; | 
| Chris@271 | 69 | 
| Chris@272 | 70     int rounded = int(ratio); | 
| Chris@271 | 71     RealTime rdrt = rtick * rounded; | 
| Chris@271 | 72 | 
| Chris@908 | 73     sv_frame_t left = RealTime::realTime2Frame(rdrt, rate); | 
| Chris@908 | 74     resolution = int(RealTime::realTime2Frame(rtick, rate)); | 
| Chris@908 | 75     sv_frame_t right = left + resolution; | 
| Chris@271 | 76 | 
| Chris@587 | 77 //    SVDEBUG << "TimeRulerLayer::snapToFeatureFrame: type " | 
| Chris@272 | 78 //              << int(snap) << ", frame " << frame << " (time " | 
| Chris@272 | 79 //              << rt << ", tick " << rtick << ", rounded " << rdrt << ") "; | 
| Chris@272 | 80 | 
| Chris@271 | 81     switch (snap) { | 
| Chris@271 | 82 | 
| Chris@271 | 83     case SnapLeft: | 
| Chris@271 | 84         frame = left; | 
| Chris@271 | 85         break; | 
| Chris@271 | 86 | 
| Chris@271 | 87     case SnapRight: | 
| Chris@271 | 88         frame = right; | 
| Chris@271 | 89         break; | 
| Chris@271 | 90 | 
| Chris@271 | 91     case SnapNearest: | 
| Chris@271 | 92     { | 
| Chris@989 | 93         if (llabs(frame - left) > llabs(right - frame)) { | 
| Chris@271 | 94             frame = right; | 
| Chris@271 | 95         } else { | 
| Chris@271 | 96             frame = left; | 
| Chris@271 | 97         } | 
| Chris@271 | 98         break; | 
| Chris@271 | 99     } | 
| Chris@271 | 100 | 
| Chris@271 | 101     case SnapNeighbouring: | 
| Chris@271 | 102     { | 
| Chris@271 | 103         int dl = -1, dr = -1; | 
| Chris@271 | 104         int x = v->getXForFrame(frame); | 
| Chris@271 | 105 | 
| Chris@271 | 106         if (left > v->getStartFrame() && | 
| Chris@271 | 107             left < v->getEndFrame()) { | 
| Chris@271 | 108             dl = abs(v->getXForFrame(left) - x); | 
| Chris@271 | 109         } | 
| Chris@271 | 110 | 
| Chris@271 | 111         if (right > v->getStartFrame() && | 
| Chris@271 | 112             right < v->getEndFrame()) { | 
| Chris@271 | 113             dr = abs(v->getXForFrame(right) - x); | 
| Chris@271 | 114         } | 
| Chris@271 | 115 | 
| Chris@271 | 116         int fuzz = 2; | 
| Chris@271 | 117 | 
| Chris@271 | 118         if (dl >= 0 && dr >= 0) { | 
| Chris@271 | 119             if (dl < dr) { | 
| Chris@271 | 120                 if (dl <= fuzz) { | 
| Chris@271 | 121                     frame = left; | 
| Chris@271 | 122                 } | 
| Chris@271 | 123             } else { | 
| Chris@271 | 124                 if (dr < fuzz) { | 
| Chris@271 | 125                     frame = right; | 
| Chris@271 | 126                 } | 
| Chris@271 | 127             } | 
| Chris@271 | 128         } else if (dl >= 0) { | 
| Chris@271 | 129             if (dl <= fuzz) { | 
| Chris@271 | 130                 frame = left; | 
| Chris@271 | 131             } | 
| Chris@271 | 132         } else if (dr >= 0) { | 
| Chris@271 | 133             if (dr <= fuzz) { | 
| Chris@271 | 134                 frame = right; | 
| Chris@271 | 135             } | 
| Chris@271 | 136         } | 
| Chris@271 | 137     } | 
| Chris@271 | 138     } | 
| Chris@271 | 139 | 
| Chris@587 | 140 //    SVDEBUG << " -> " << frame << " (resolution = " << resolution << ")" << endl; | 
| Chris@272 | 141 | 
| Chris@271 | 142     return true; | 
| Chris@271 | 143 } | 
| Chris@271 | 144 | 
| Chris@1346 | 145 int64_t | 
| Chris@1341 | 146 TimeRulerLayer::getMajorTickUSec(LayerGeometryProvider *v, | 
| Chris@1341 | 147                                  bool &quarterTicks) const | 
| Chris@271 | 148 { | 
| Chris@1341 | 149     // return value is in microseconds | 
| Chris@1341 | 150     if (!m_model || !v) return 1000 * 1000; | 
| Chris@271 | 151 | 
| Chris@908 | 152     sv_samplerate_t sampleRate = m_model->getSampleRate(); | 
| Chris@1341 | 153     if (!sampleRate) return 1000 * 1000; | 
| Chris@271 | 154 | 
| Chris@908 | 155     sv_frame_t startFrame = v->getStartFrame(); | 
| Chris@908 | 156     sv_frame_t endFrame = v->getEndFrame(); | 
| Chris@271 | 157 | 
| Chris@1341 | 158     int minPixelSpacing = ViewManager::scalePixelSize(50); | 
| Chris@271 | 159 | 
| Chris@271 | 160     RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); | 
| Chris@271 | 161     RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); | 
| Chris@271 | 162 | 
| Chris@918 | 163     int count = v->getPaintWidth() / minPixelSpacing; | 
| Chris@271 | 164     if (count < 1) count = 1; | 
| Chris@271 | 165     RealTime rtGap = (rtEnd - rtStart) / count; | 
| Chris@271 | 166 | 
| Chris@1346 | 167     int64_t incus; | 
| Chris@271 | 168     quarterTicks = false; | 
| Chris@271 | 169 | 
| Chris@271 | 170     if (rtGap.sec > 0) { | 
| Chris@1341 | 171         incus = 1000 * 1000; | 
| Chris@1266 | 172         int s = rtGap.sec; | 
| Chris@1341 | 173         if (s > 0) { incus *= 5; s /= 5; } | 
| Chris@1341 | 174         if (s > 0) { incus *= 2; s /= 2; } | 
| Chris@1341 | 175         if (s > 0) { incus *= 6; s /= 6; quarterTicks = true; } | 
| Chris@1341 | 176         if (s > 0) { incus *= 5; s /= 5; quarterTicks = false; } | 
| Chris@1341 | 177         if (s > 0) { incus *= 2; s /= 2; } | 
| Chris@1341 | 178         if (s > 0) { incus *= 6; s /= 6; quarterTicks = true; } | 
| Chris@1266 | 179         while (s > 0) { | 
| Chris@1341 | 180             incus *= 10; | 
| Chris@1266 | 181             s /= 10; | 
| Chris@1266 | 182             quarterTicks = false; | 
| Chris@1266 | 183         } | 
| Chris@1341 | 184     } else if (rtGap.msec() > 0) { | 
| Chris@1341 | 185         incus = 1000; | 
| Chris@1341 | 186         int ms = rtGap.msec(); | 
| Chris@1341 | 187         if (ms > 0) { incus *= 10; ms /= 10; } | 
| Chris@1341 | 188         if (ms > 0) { incus *= 10; ms /= 10; } | 
| Chris@1341 | 189         if (ms > 0) { incus *= 5; ms /= 5; } | 
| Chris@1341 | 190         if (ms > 0) { incus *= 2; ms /= 2; } | 
| Chris@271 | 191     } else { | 
| Chris@1341 | 192         incus = 1; | 
| Chris@1341 | 193         int us = rtGap.usec(); | 
| Chris@1341 | 194         if (us > 0) { incus *= 10; us /= 10; } | 
| Chris@1341 | 195         if (us > 0) { incus *= 10; us /= 10; } | 
| Chris@1341 | 196         if (us > 0) { incus *= 5; us /= 5; } | 
| Chris@1341 | 197         if (us > 0) { incus *= 2; us /= 2; } | 
| Chris@271 | 198     } | 
| Chris@271 | 199 | 
| Chris@1341 | 200     return incus; | 
| Chris@1341 | 201 } | 
| Chris@1341 | 202 | 
| Chris@1341 | 203 int | 
| Chris@1341 | 204 TimeRulerLayer::getXForUSec(LayerGeometryProvider *v, double us) const | 
| Chris@1341 | 205 { | 
| Chris@1341 | 206     sv_samplerate_t sampleRate = m_model->getSampleRate(); | 
| Chris@1341 | 207     double dframe = (us * sampleRate) / 1000000.0; | 
| Chris@1341 | 208     double eps = 1e-7; | 
| Chris@1341 | 209     sv_frame_t frame = sv_frame_t(floor(dframe + eps)); | 
| Chris@1341 | 210     int x; | 
| Chris@1341 | 211 | 
| Chris@1341 | 212     ZoomLevel zoom = v->getZoomLevel(); | 
| Chris@1341 | 213 | 
| Chris@1341 | 214     if (zoom.zone == ZoomLevel::FramesPerPixel) { | 
| Chris@1341 | 215 | 
| Chris@1341 | 216         frame /= zoom.level; | 
| Chris@1341 | 217         frame *= zoom.level; // so frame corresponds to an exact pixel | 
| Chris@1341 | 218 | 
| Chris@1341 | 219         x = v->getXForFrame(frame); | 
| Chris@1341 | 220 | 
| Chris@1341 | 221     } else { | 
| Chris@1341 | 222 | 
| Chris@1341 | 223         double off = dframe - double(frame); | 
| Chris@1341 | 224         int x0 = v->getXForFrame(frame); | 
| Chris@1341 | 225         int x1 = v->getXForFrame(frame + 1); | 
| Chris@1341 | 226 | 
| Chris@1341 | 227         x = int(x0 + off * (x1 - x0)); | 
| Chris@1341 | 228     } | 
| Chris@1341 | 229 | 
| Chris@1341 | 230 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1341 | 231     cerr << "Considering frame = " << frame << ", x = " << x << endl; | 
| Chris@1341 | 232 #endif | 
| Chris@1341 | 233 | 
| Chris@1341 | 234     return x; | 
| Chris@271 | 235 } | 
| Chris@271 | 236 | 
| Chris@0 | 237 void | 
| Chris@916 | 238 TimeRulerLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 
| Chris@0 | 239 { | 
| Chris@370 | 240 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 241     SVCERR << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() | 
| Chris@1346 | 242            << ") [" << rect.width() << "x" << rect.height() << "]" << endl; | 
| Chris@370 | 243 #endif | 
| Chris@0 | 244 | 
| Chris@0 | 245     if (!m_model || !m_model->isOK()) return; | 
| Chris@0 | 246 | 
| Chris@908 | 247     sv_samplerate_t sampleRate = m_model->getSampleRate(); | 
| Chris@0 | 248     if (!sampleRate) return; | 
| Chris@0 | 249 | 
| Chris@908 | 250     sv_frame_t startFrame = v->getFrameForX(rect.x() - 50); | 
| Chris@0 | 251 | 
| Chris@370 | 252 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 253     SVCERR << "start frame = " << startFrame << endl; | 
| Chris@370 | 254 #endif | 
| Chris@0 | 255 | 
| Chris@0 | 256     bool quarter = false; | 
| Chris@1346 | 257     int64_t incus = getMajorTickUSec(v, quarter); | 
| Chris@1346 | 258     int64_t us = int64_t(floor(1000.0 * 1000.0 * (double(startFrame) / | 
| Chris@1346 | 259                                                   double(sampleRate)))); | 
| Chris@1341 | 260     us = (us / incus) * incus - incus; | 
| Chris@0 | 261 | 
| Chris@370 | 262 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 263     SVCERR << "start us = " << us << " at step " << incus << endl; | 
| Chris@370 | 264 #endif | 
| Chris@370 | 265 | 
| Chris@1345 | 266     Preferences *prefs = Preferences::getInstance(); | 
| Chris@1345 | 267     auto origTimeTextMode = prefs->getTimeToTextMode(); | 
| Chris@1345 | 268     if (incus < 1000) { | 
| Chris@1345 | 269         // Temporarily switch to usec display mode (if we aren't using | 
| Chris@1345 | 270         // it already) | 
| Chris@1345 | 271         prefs->blockSignals(true); | 
| Chris@1345 | 272         prefs->setTimeToTextMode(Preferences::TimeToTextUs); | 
| Chris@1345 | 273     } | 
| Chris@1345 | 274 | 
| Chris@370 | 275     // Calculate the number of ticks per increment -- approximate | 
| Chris@370 | 276     // values for x and frame counts here will do, no rounding issue. | 
| Chris@1341 | 277     // We always use the exact incus in our calculations for where to | 
| Chris@370 | 278     // draw the actual ticks or lines. | 
| Chris@370 | 279 | 
| Chris@370 | 280     int minPixelSpacing = 50; | 
| Chris@1346 | 281     sv_frame_t incFrame = lrint((double(incus) * sampleRate) / 1000000); | 
| Chris@1326 | 282     int incX = int(round(v->getZoomLevel().framesToPixels(double(incFrame)))); | 
| Chris@0 | 283     int ticks = 10; | 
| Chris@0 | 284     if (incX < minPixelSpacing * 2) { | 
| Chris@1266 | 285         ticks = quarter ? 4 : 5; | 
| Chris@0 | 286     } | 
| Chris@0 | 287 | 
| Chris@370 | 288     QColor greyColour = getPartialShades(v)[1]; | 
| Chris@0 | 289 | 
| Chris@370 | 290     paint.save(); | 
| Chris@0 | 291 | 
| Chris@832 | 292     // Do not label time zero - we now overlay an opaque area over | 
| Chris@832 | 293     // time < 0 which would cut it in half | 
| Chris@1341 | 294     int minlabel = 1; // us | 
| Chris@1021 | 295 | 
| Chris@0 | 296     while (1) { | 
| Chris@0 | 297 | 
| Chris@370 | 298         // frame is used to determine where to draw the lines, so it | 
| Chris@370 | 299         // needs to correspond to an exact pixel (so that we don't get | 
| Chris@370 | 300         // a different pixel when scrolling a small amount and | 
| Chris@370 | 301         // re-drawing with a different start frame). | 
| Chris@370 | 302 | 
| Chris@1346 | 303         double dus = double(us); | 
| Chris@370 | 304 | 
| Chris@1341 | 305         int x = getXForUSec(v, dus); | 
| Chris@0 | 306 | 
| Chris@370 | 307         if (x >= rect.x() + rect.width() + 50) { | 
| Chris@370 | 308 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 309             SVCERR << "X well out of range, ending here" << endl; | 
| Chris@370 | 310 #endif | 
| Chris@370 | 311             break; | 
| Chris@370 | 312         } | 
| Chris@0 | 313 | 
| Chris@1341 | 314         if (x >= rect.x() - 50 && us >= minlabel) { | 
| Chris@0 | 315 | 
| Chris@1342 | 316             RealTime rt = RealTime::fromMicroseconds(us); | 
| Chris@375 | 317 | 
| Chris@370 | 318 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 319             SVCERR << "X in range, drawing line here for time " << rt.toText() << " (usec = " << us << ")" << endl; | 
| Chris@370 | 320 #endif | 
| Chris@0 | 321 | 
| Chris@370 | 322             QString text(QString::fromStdString(rt.toText())); | 
| Chris@1345 | 323 | 
| Chris@370 | 324             QFontMetrics metrics = paint.fontMetrics(); | 
| Chris@370 | 325             int tw = metrics.width(text); | 
| Chris@0 | 326 | 
| Chris@370 | 327             if (tw < 50 && | 
| Chris@370 | 328                 (x < rect.x() - tw/2 || | 
| Chris@370 | 329                  x >= rect.x() + rect.width() + tw/2)) { | 
| Chris@370 | 330 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 331                 SVCERR << "hm, maybe X isn't in range after all (x = " << x << ", tw = " << tw << ", rect.x() = " << rect.x() << ", rect.width() = " << rect.width() << ")" << endl; | 
| Chris@370 | 332 #endif | 
| Chris@370 | 333             } | 
| Chris@70 | 334 | 
| Chris@370 | 335             paint.setPen(greyColour); | 
| Chris@918 | 336             paint.drawLine(x, 0, x, v->getPaintHeight()); | 
| Chris@370 | 337 | 
| Chris@370 | 338             paint.setPen(getBaseQColor()); | 
| Chris@370 | 339             paint.drawLine(x, 0, x, 5); | 
| Chris@918 | 340             paint.drawLine(x, v->getPaintHeight() - 6, x, v->getPaintHeight() - 1); | 
| Chris@370 | 341 | 
| Chris@370 | 342             int y; | 
| Chris@370 | 343             switch (m_labelHeight) { | 
| Chris@370 | 344             default: | 
| Chris@370 | 345             case LabelTop: | 
| Chris@370 | 346                 y = 6 + metrics.ascent(); | 
| Chris@370 | 347                 break; | 
| Chris@370 | 348             case LabelMiddle: | 
| Chris@918 | 349                 y = v->getPaintHeight() / 2 - metrics.height() / 2 + metrics.ascent(); | 
| Chris@370 | 350                 break; | 
| Chris@370 | 351             case LabelBottom: | 
| Chris@918 | 352                 y = v->getPaintHeight() - metrics.height() + metrics.ascent() - 6; | 
| Chris@370 | 353             } | 
| Chris@370 | 354 | 
| Chris@370 | 355             if (v->getViewManager() && v->getViewManager()->getOverlayMode() != | 
| Chris@370 | 356                 ViewManager::NoOverlays) { | 
| Chris@370 | 357 | 
| Chris@919 | 358                 if (v->getView()->getLayer(0) == this) { | 
| Chris@370 | 359                     // backmost layer, don't worry about outlining the text | 
| Chris@370 | 360                     paint.drawText(x+2 - tw/2, y, text); | 
| Chris@370 | 361                 } else { | 
| Chris@1078 | 362                     PaintAssistant::drawVisibleText(v, paint, x+2 - tw/2, y, text, PaintAssistant::OutlinedText); | 
| Chris@370 | 363                 } | 
| Chris@70 | 364             } | 
| Chris@70 | 365         } | 
| Chris@0 | 366 | 
| Chris@1266 | 367         paint.setPen(greyColour); | 
| Chris@0 | 368 | 
| Chris@1266 | 369         for (int i = 1; i < ticks; ++i) { | 
| Chris@370 | 370 | 
| Chris@1346 | 371             dus = double(us) + (i * double(incus)) / ticks; | 
| Chris@370 | 372 | 
| Chris@1341 | 373             x = getXForUSec(v, dus); | 
| Chris@370 | 374 | 
| Chris@370 | 375             if (x < rect.x() || x >= rect.x() + rect.width()) { | 
| Chris@370 | 376 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 377 //                SVCERR << "tick " << i << ": X out of range, going on to next tick" << endl; | 
| Chris@370 | 378 #endif | 
| Chris@370 | 379                 continue; | 
| Chris@370 | 380             } | 
| Chris@370 | 381 | 
| Chris@370 | 382 #ifdef DEBUG_TIME_RULER_LAYER | 
| Chris@1346 | 383             SVCERR << "tick " << i << " in range, drawing at " << x << endl; | 
| Chris@370 | 384 #endif | 
| Chris@370 | 385 | 
| Chris@1266 | 386             int sz = 5; | 
| Chris@1266 | 387             if (ticks == 10) { | 
| Chris@1266 | 388                 if ((i % 2) == 1) { | 
| Chris@1266 | 389                     if (i == 5) { | 
| Chris@1266 | 390                         paint.drawLine(x, 0, x, v->getPaintHeight()); | 
| Chris@1266 | 391                     } else sz = 3; | 
| Chris@1266 | 392                 } else { | 
| Chris@1266 | 393                     sz = 7; | 
| Chris@1266 | 394                 } | 
| Chris@1266 | 395             } | 
| Chris@1266 | 396             paint.drawLine(x, 0, x, sz); | 
| Chris@1266 | 397             paint.drawLine(x, v->getPaintHeight() - sz - 1, x, v->getPaintHeight() - 1); | 
| Chris@1266 | 398         } | 
| Chris@375 | 399 | 
| Chris@1341 | 400         us += incus; | 
| Chris@0 | 401     } | 
| Chris@1345 | 402 | 
| Chris@1345 | 403     prefs->setTimeToTextMode(origTimeTextMode); | 
| Chris@1345 | 404     prefs->blockSignals(false); | 
| Chris@0 | 405 | 
| Chris@0 | 406     paint.restore(); | 
| Chris@0 | 407 } | 
| Chris@287 | 408 | 
| Chris@287 | 409 int | 
| Chris@287 | 410 TimeRulerLayer::getDefaultColourHint(bool darkbg, bool &impose) | 
| Chris@287 | 411 { | 
| Chris@287 | 412     impose = true; | 
| Chris@287 | 413     return ColourDatabase::getInstance()->getColourIndex | 
| Chris@287 | 414         (QString(darkbg ? "White" : "Black")); | 
| Chris@287 | 415 } | 
| Chris@287 | 416 | 
| Chris@335 | 417 QString TimeRulerLayer::getLayerPresentationName() const | 
| Chris@335 | 418 { | 
| Chris@335 | 419     LayerFactory *factory = LayerFactory::getInstance(); | 
| Chris@335 | 420     QString layerName = factory->getLayerPresentationName | 
| Chris@335 | 421         (factory->getLayerType(this)); | 
| Chris@335 | 422     return layerName; | 
| Chris@335 | 423 } | 
| Chris@335 | 424 | 
| Chris@316 | 425 void | 
| Chris@316 | 426 TimeRulerLayer::toXml(QTextStream &stream, | 
| Chris@316 | 427                       QString indent, QString extraAttributes) const | 
| Chris@6 | 428 { | 
| Chris@316 | 429     SingleColourLayer::toXml(stream, indent, extraAttributes); | 
| Chris@6 | 430 } | 
| Chris@6 | 431 | 
| Chris@11 | 432 void | 
| Chris@11 | 433 TimeRulerLayer::setProperties(const QXmlAttributes &attributes) | 
| Chris@11 | 434 { | 
| Chris@287 | 435     SingleColourLayer::setProperties(attributes); | 
| Chris@11 | 436 } | 
| Chris@11 | 437 |