コード例 #1
0
void ProfileGraphicsView::plot_depth_scale()
{
    int i, maxdepth, marker;
    static text_render_options_t tro = {DEPTH_TEXT_SIZE, SAMPLE_DEEP, RIGHT, MIDDLE};

    /* Depth markers: every 30 ft or 10 m*/
    maxdepth = get_maxdepth(&gc.pi);
    gc.topy = 0;
    gc.bottomy = maxdepth;

    switch (prefs.units.length) {
    case units::METERS:
        marker = 10000;
        break;
    case units::FEET:
        marker = 9144;
        break;	/* 30 ft */
    }

    QColor c(getColor(DEPTH_GRID));

    /* don't write depth labels all the way to the bottom as
     * there may be other graphs below the depth plot (like
     * partial pressure graphs) where this would look out
     * of place - so we only make sure that we print the next
     * marker below the actual maxdepth of the dive */
    depthMarkers = new QGraphicsRectItem();
    for (i = marker; i <= gc.pi.maxdepth + marker; i += marker) {
        double d = get_depth_units(i, NULL, NULL);
        plot_text(&tro, QPointF(-0.002, i), QString::number(d), depthMarkers);
    }
    scene()->addItem(depthMarkers);
    depthMarkers->setPos(depthMarkers->pos().x() - 10, 0);
}
コード例 #2
0
void ProfileGraphicsView::plot_single_temp_text(int sec, int mkelvin)
{
    double deg;
    const char *unit;
    static text_render_options_t tro = {TEMP_TEXT_SIZE, TEMP_TEXT, LEFT, TOP};
    deg = get_temp_units(mkelvin, &unit);
    plot_text(&tro, QPointF(sec, mkelvin), QString("%1%2").arg(deg, 0, 'f', 1).arg(unit)); //"%.2g%s"
}
コード例 #3
0
void ProfileGraphicsView::plot_depth_sample(struct plot_data *entry,text_render_options_t *tro)
{
    int sec = entry->sec, decimals;
    double d;

    d = get_depth_units(entry->depth, &decimals, NULL);

    plot_text(tro, QPointF(sec, entry->depth), QString("%1").arg(d, 0, 'f', 1));
}
コード例 #4
0
void ProfileGraphicsView::plot_pressure_value(int mbar, int sec, double xalign, double yalign)
{
    int pressure;
    const char *unit;

    pressure = get_pressure_units(mbar, &unit);
    static text_render_options_t tro = {PRESSURE_TEXT_SIZE, PRESSURE_TEXT, xalign, yalign};
    plot_text(&tro, QPointF(sec, mbar), QString("%1 %2").arg(pressure).arg(unit));
}
コード例 #5
0
void ProfileGraphicsView::plot_deco_text()
{
    if (prefs.profile_calc_ceiling) {
        float x = gc.leftx + (gc.rightx - gc.leftx) / 2;
        float y = gc.topy = 1.0;
        static text_render_options_t tro = {PRESSURE_TEXT_SIZE, PRESSURE_TEXT, CENTER, BOTTOM};
        gc.bottomy = 0.0;
        plot_text(&tro, QPointF(x, y), QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh));
    }
}
コード例 #6
0
void ProfileGraphicsView::plot_gas_value(int mbar, int sec, double xalign, double yalign, int o2, int he)
{
    QString gas;
    if (is_air(o2, he))
        gas = tr("air");
    else if (he == 0)
        gas = QString(tr("EAN%1")).arg((o2 + 5) / 10);
    else
        gas = QString("%1/%2").arg((o2 + 5) / 10).arg((he + 5) / 10);
    static text_render_options_t tro = {PRESSURE_TEXT_SIZE, PRESSURE_TEXT, xalign, yalign};
    plot_text(&tro, QPointF(sec, mbar), gas);

}
コード例 #7
0
void ProfileGraphicsView::plot_pp_text()
{
	double pp, dpp, m;
	int hpos;
	static text_render_options_t tro = {PP_TEXT_SIZE, PP_LINES, LEFT, MIDDLE};

	setup_pp_limits(&gc);
	pp = floor(gc.pi.maxpp * 10.0) / 10.0 + 0.2;
	dpp = pp > 4 ? 1.0 : 0.5;
	hpos = gc.pi.entry[gc.pi.nr - 1].sec;
	QColor c = profile_color[PP_LINES].first();

	for (m = 0.0; m <= pp; m += dpp) {
		QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, m), SCALEGC(hpos, m));
		QPen pen(defaultPen);
		pen.setColor(c);
		item->setPen(pen);
		scene()->addItem(item);
		plot_text(&tro, QPointF(hpos + 30, m), QString::number(m));
	}
}
コード例 #8
0
ファイル: PlotArea.C プロジェクト: Stabledog/dddbash
int PlotArea::do_plot(const char *commands, bool clear)
{
    // Discard all commands up to `G' command, if any
    int discard = -1;

    {
      const char *cmds = commands;
      while (*cmds != '\0')
	{
	  if (cmds[0] == 'G' && cmds[1] == '\n')
	    {
	      if (pending_plots > 0)
		pending_plots--;
	      
	      discard = (cmds - commands);
	    }
	  
	  while (*cmds != '\n' && *cmds != '\0')
	    cmds++;
	  if (*cmds != '\0')
	    cmds++;
	}
    }

    // Process commands
    const char *cmds = commands;
    if (discard >= 0)
    {
	cmds += discard;
	assert(cmds[0] == 'G');
	assert(cmds[1] == '\n');
    }

#if 0				// FIXME: Not thoroughly tested yet  -AZ
    if (discard < 0 && pending_plots > 0)
	return discard;
#endif

    while (cmds[0] != '\0')
    {
	const char *command_begin = cmds;

	// Move CMDS to the next line
	while (*cmds != '\0' && *cmds != '\n')
	    cmds++;
	if (*cmds == '\0')
	    break;		// Command is incomplete - don't do it
	assert(*cmds == '\n');
	cmds++;

	// Copy current command to a NULL-terminated string. Otherwise, 
        // sscanf() takes far too much time.
	const int len_ = cmds-command_begin-1;
	assert(len_ >= 0);
	const string command_s(command_begin,len_);

	const char *command = command_s.chars();
	switch (command[0])
	{
	case 'V':
	    if (win)
		plot_vector(command);
	    break;

	case 'M':
	    if (win)
		plot_move(command);
	    break;

	case 'T':
	    if (win)
		plot_text(command);
	    break;

	case 'J':
	    if (win)
		plot_justify(command);
	    break;

	case 'L':
	    if (win)
		plot_linetype(command);
	    break;

	case 'P':
	    if (win)
		plot_point(command);
	    break;

	case 'G':
	    plot_reset(command);
	    if (win && clear)
		plot_clear(command);
	    break;

	case 'E':
	case 'R':
	    if (win)
		plot_nop(command);
	    break;

	default:
	    plot_unknown(command);
	    break;
	}
    }

    return discard;
}
コード例 #9
0
void ProfileGraphicsView::plot_depth_profile()
{
    int i, incr;
    int sec, depth;
    struct plot_data *entry;
    int maxtime, maxdepth, marker, maxline;
    int increments[8] = { 10, 20, 30, 60, 5*60, 10*60, 15*60, 30*60 };

    /* Get plot scaling limits */
    maxtime = get_maxtime(&gc.pi);
    maxdepth = get_maxdepth(&gc.pi);

    gc.maxtime = maxtime;

    /* Time markers: at most every 10 seconds, but no more than 12 markers.
     * We start out with 10 seconds and increment up to 30 minutes,
     * depending on the dive time.
     * This allows for 6h dives - enough (I hope) for even the craziest
     * divers - but just in case, for those 8h depth-record-breaking dives,
     * we double the interval if this still doesn't get us to 12 or fewer
     * time markers */
    i = 0;
    while (maxtime / increments[i] > 12 && i < 7)
        i++;
    incr = increments[i];
    while (maxtime / incr > 12)
        incr *= 2;

    gc.leftx = 0;
    gc.rightx = maxtime;
    gc.topy = 0;
    gc.bottomy = 1.0;

    last_gc = gc;

    QColor c = getColor(TIME_GRID);
    for (i = incr; i < maxtime; i += incr) {
        QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(i, 0), SCALEGC(i, 1));
        QPen pen(defaultPen);
        pen.setColor(c);
        item->setPen(pen);
        scene()->addItem(item);
    }

    timeMarkers = new QGraphicsRectItem();
    /* now the text on the time markers */
    struct text_render_options tro = {DEPTH_TEXT_SIZE, TIME_TEXT, CENTER, LINE_DOWN};
    if (maxtime < 600) {
        /* Be a bit more verbose with shorter dives */
        for (i = incr; i < maxtime; i += incr)
            plot_text(&tro, QPointF(i, 0), QString("%1:%2").arg(i/60).arg(i%60, 2, 10, QChar('0')), timeMarkers);
    } else {
        /* Only render the time on every second marker for normal dives */
        for (i = incr; i < maxtime; i += 2 * incr)
            plot_text(&tro, QPointF(i, 0), QString("%1").arg(QString::number(i/60)), timeMarkers);
    }
    timeMarkers->setPos(0,0);
    scene()->addItem(timeMarkers);

    /* Depth markers: every 30 ft or 10 m*/
    gc.leftx = 0;
    gc.rightx = 1.0;
    gc.topy = 0;
    gc.bottomy = maxdepth;
    switch (prefs.units.length) {
    case units::METERS:
        marker = 10000;
        break;
    case units::FEET:
        marker = 9144;
        break;	/* 30 ft */
    }
    maxline = qMax(gc.pi.maxdepth + marker, maxdepth * 2 / 3);

    c = getColor(DEPTH_GRID);

    for (i = marker; i < maxline; i += marker) {
        QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, i), SCALEGC(1, i));
        QPen pen(defaultPen);
        pen.setColor(c);
        item->setPen(pen);
        scene()->addItem(item);
    }

    gc.leftx = 0;
    gc.rightx = maxtime;
    c = getColor(MEAN_DEPTH);

    /* Show mean depth */
    if (! gc.printer) {
        QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, gc.pi.meandepth),
                SCALEGC(gc.pi.entry[gc.pi.nr - 1].sec, gc.pi.meandepth));
        QPen pen(defaultPen);
        pen.setColor(c);
        item->setPen(pen);
        scene()->addItem(item);
    }

#if 0
    /*
     * These are good for debugging text placement etc,
     * but not for actual display..
     */
    if (0) {
        plot_smoothed_profile(gc, pi);
        plot_minmax_profile(gc, pi);
    }
#endif

    /* Do the depth profile for the neat fill */
    gc.topy = 0;
    gc.bottomy = maxdepth;

    entry = gc.pi.entry;

    QPolygonF p;
    QLinearGradient pat(0.0,0.0,0.0,scene()->height());
    QGraphicsPolygonItem *neatFill = NULL;

    p.append(QPointF(SCALEGC(0, 0)));
    for (i = 0; i < gc.pi.nr; i++, entry++)
        p.append(QPointF(SCALEGC(entry->sec, entry->depth)));

    /* Show any ceiling we may have encountered */
    if (prefs.profile_dc_ceiling) {
        for (i = gc.pi.nr - 1; i >= 0; i--, entry--) {
            if (!entry->in_deco) {
                /* not in deco implies this is a safety stop, no ceiling */
                p.append(QPointF(SCALEGC(entry->sec, 0)));
            } else if (entry->stopdepth < entry->depth) {
                p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
            } else {
                p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
            }
        }
    }
    pat.setColorAt(1, getColor(DEPTH_BOTTOM));
    pat.setColorAt(0, getColor(DEPTH_TOP));

    neatFill = new QGraphicsPolygonItem();
    neatFill->setPolygon(p);
    neatFill->setBrush(QBrush(pat));
    neatFill->setPen(QPen(QBrush(Qt::transparent),0));
    scene()->addItem(neatFill);


    /* if the user wants the deco ceiling more visible, do that here (this
     * basically draws over the background that we had allowed to shine
     * through so far) */
    if (prefs.profile_dc_ceiling && prefs.profile_red_ceiling) {
        p.clear();
        pat.setColorAt(0, getColor(CEILING_SHALLOW));
        pat.setColorAt(1, getColor(CEILING_DEEP));

        entry = gc.pi.entry;
        p.append(QPointF(SCALEGC(0, 0)));
        for (i = 0; i < gc.pi.nr; i++, entry++) {
            if (entry->in_deco && entry->stopdepth) {
                if (entry->stopdepth < entry->depth) {
                    p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
                } else {
                    p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
                }
            } else {
                p.append(QPointF(SCALEGC(entry->sec, 0)));
            }
        }

        neatFill = new QGraphicsPolygonItem();
        neatFill->setBrush(QBrush(pat));
        neatFill->setPolygon(p);
        neatFill->setPen(QPen(QBrush(Qt::NoBrush),0));
        scene()->addItem(neatFill);
    }

    /* finally, plot the calculated ceiling over all this */
    if (prefs.profile_calc_ceiling) {
        pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
        pat.setColorAt(1, getColor(CALC_CEILING_DEEP));

        entry = gc.pi.entry;
        p.clear();
        p.append(QPointF(SCALEGC(0, 0)));
        for (i = 0; i < gc.pi.nr; i++, entry++) {
            if (entry->ceiling)
                p.append(QPointF(SCALEGC(entry->sec, entry->ceiling)));
            else
                p.append(QPointF(SCALEGC(entry->sec, 0)));
        }
        p.append(QPointF(SCALEGC((entry-1)->sec, 0)));
        neatFill = new QGraphicsPolygonItem();
        neatFill->setPolygon(p);
        neatFill->setPen(QPen(QBrush(Qt::NoBrush),0));
        neatFill->setBrush(pat);
        scene()->addItem(neatFill);
    }

    /* plot the calculated ceiling for all tissues */
    if (prefs.profile_calc_ceiling && prefs.calc_all_tissues) {
        int k;
        for (k=0; k<16; k++) {
            pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
            pat.setColorAt(1, QColor(100, 100, 100, 50));

            entry = gc.pi.entry;
            p.clear();
            p.append(QPointF(SCALEGC(0, 0)));
            for (i = 0; i < gc.pi.nr; i++, entry++) {
                if ((entry->ceilings)[k])
                    p.append(QPointF(SCALEGC(entry->sec, (entry->ceilings)[k])));
                else
                    p.append(QPointF(SCALEGC(entry->sec, 0)));
            }
            p.append(QPointF(SCALEGC((entry-1)->sec, 0)));
            neatFill = new QGraphicsPolygonItem();
            neatFill->setPolygon(p);
            neatFill->setBrush(pat);
            scene()->addItem(neatFill);
        }
    }
    /* next show where we have been bad and crossed the dc's ceiling */
    if (prefs.profile_dc_ceiling) {
        pat.setColorAt(0, getColor(CEILING_SHALLOW));
        pat.setColorAt(1, getColor(CEILING_DEEP));

        entry = gc.pi.entry;
        p.clear();
        p.append(QPointF(SCALEGC(0, 0)));
        for (i = 0; i < gc.pi.nr; i++, entry++)
            p.append(QPointF(SCALEGC(entry->sec, entry->depth)));

        for (i-- , entry--; i >= 0; i--, entry--) {
            if (entry->in_deco && entry->stopdepth > entry->depth) {
                p.append(QPointF(SCALEGC(entry->sec, entry->stopdepth)));
            } else {
                p.append(QPointF(SCALEGC(entry->sec, entry->depth)));
            }
        }
    }
    neatFill = new QGraphicsPolygonItem();
    neatFill->setPolygon(p);
    neatFill->setPen(QPen(QBrush(Qt::NoBrush),0));
    neatFill->setBrush(QBrush(pat));
    scene()->addItem(neatFill);

    /* Now do it again for the velocity colors */
    entry = gc.pi.entry;
    for (i = 1; i < gc.pi.nr; i++) {
        entry++;
        sec = entry->sec;
        /* we want to draw the segments in different colors
         * representing the vertical velocity, so we need to
         * chop this into short segments */
        depth = entry->depth;
        QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(entry[-1].sec, entry[-1].depth), SCALEGC(sec, depth));
        QPen pen(defaultPen);
        pen.setColor(getColor((color_indice_t)(VELOCITY_COLORS_START_IDX + entry->velocity)));
        item->setPen(pen);
        scene()->addItem(item);
    }
}
コード例 #10
0
void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
{
    struct divecomputer *dc = NULL;

    if (d)
        dc = select_dc(&d->dc);

    if (!forceRedraw && dive == d && (d && dc == diveDC))
        return;

    clear();
    dive = d;
    diveDC = d ? dc : NULL;

    if (!isVisible() || !dive || !mainWindow()) {
        return;
    }
    setBackgroundBrush(getColor(BACKGROUND));

    // best place to put the focus stealer code.
    setFocusProxy(mainWindow()->dive_list());
    scene()->setSceneRect(0,0, viewport()->width()-50, viewport()->height()-50);

    toolTip = new ToolTipItem();
    installEventFilter(toolTip);
    scene()->addItem(toolTip);
    if (printMode)
        toolTip->setVisible(false);

    // Fix this for printing / screen later.
    // plot_set_scale(scale_mode_t);

    if (!dc || !dc->samples) {
        dc = fake_dc(dc);
    }

    QString nick = get_dc_nickname(dc->model, dc->deviceid);
    if (nick.isEmpty())
        nick = QString(dc->model);

    if (nick.isEmpty())
        nick = tr("unknown divecomputer");

    if ( tr("unknown divecomputer") == nick) {
        mode = PLAN;
    } else {
        mode = DIVE;
    }

    /*
     * Set up limits that are independent of
     * the dive computer
     */
    calculate_max_limits(dive, dc, &gc);

    QRectF profile_grid_area = scene()->sceneRect();
    gc.maxx = (profile_grid_area.width() - 2 * profile_grid_area.x());
    gc.maxy = (profile_grid_area.height() - 2 * profile_grid_area.y());

    /* This is per-dive-computer */
    gc.pi = *create_plot_info(dive, dc, &gc);

    /* Bounding box */
    QPen pen = defaultPen;
    pen.setColor(getColor(TIME_GRID));
    QGraphicsRectItem *rect = new QGraphicsRectItem(profile_grid_area);
    rect->setPen(pen);
    scene()->addItem(rect);

    /* Depth profile */
    plot_depth_profile();
    plot_events(dc);

    if (rulerEnabled && !printMode)
        create_ruler();

    /* Temperature profile */
    plot_temperature_profile();

    /* Cylinder pressure plot */
    plot_cylinder_pressure();

    /* Text on top of all graphs.. */
    plot_temperature_text();
    plot_depth_text();
    plot_cylinder_pressure_text();
    plot_deco_text();

    /* Put the dive computer name in the lower left corner */
    gc.leftx = 0;
    gc.rightx = 1.0;
    gc.topy = 0;
    gc.bottomy = 1.0;

    text_render_options_t computer = {DC_TEXT_SIZE, TIME_TEXT, LEFT, TOP};
    diveComputer = plot_text(&computer, QPointF(gc.leftx, gc.bottomy), nick);
    // The Time ruler should be right after the DiveComputer:
    timeMarkers->setPos(0, diveComputer->y());

    if (PP_GRAPHS_ENABLED) {
        plot_pp_gas_profile();
        plot_pp_text();
    }

    plot_depth_scale();

#if 0
    if (gc->printer) {
        free(pi->entry);
        last_pi_entry = pi->entry = NULL;
        pi->nr = 0;
    }
#endif

    QRectF r = scene()->itemsBoundingRect();
    scene()->setSceneRect(r.x() - 15, r.y() -15, r.width() + 30, r.height() + 30);
    if (zoomLevel == 0) {
        fitInView(sceneRect());
    }
    toolTip->readPos();

    if(mode == PLAN) {
        timeEditor = new GraphicsTextEditor();
        timeEditor->setPlainText( dive->duration.seconds ? QString::number(dive->duration.seconds/60) : tr("Set Duration: 10 minutes"));
        timeEditor->setPos(profile_grid_area.width() - timeEditor->boundingRect().width(), timeMarkers->y());
        timeEditor->document();
        connect(timeEditor, SIGNAL(editingFinished(QString)), this, SLOT(edit_dive_time(QString)));
        scene()->addItem(timeEditor);
    }

    if (!printMode)
        addControlItems();

    if (rulerEnabled && !printMode)
        add_ruler();
}
コード例 #11
0
ファイル: tetris.c プロジェクト: phillid/tetris
void
main_loop()
{
	struct colour *board[WIDTH_CELLS][HEIGHT_CELLS];
	SDL_Event e = {0};
	bool running = false;
	bool game_over = false;
	int i = 0;
	int x = 0;
	int y = 0;
	int score = 0;
	int last_x = 0;
	int last_y = 1;
	struct piece held;
	new_piece(&held);

	TTF_Font *font = TTF_OpenFont(FONT_FILE, FONT_SIZE);
	if (!font) {
		printf("TTF_OpenFont: %s\n", TTF_GetError());
		return;
	}

	for (y = 0; y < HEIGHT_CELLS; y++)
		for (x = 0; x < WIDTH_CELLS; x++)
			board[x][y] = &(palette[0]);

	running = true;
	last_x = last_y = x = y = 0;
	SDL_AddTimer(INTERVAL_NORMAL, &gravity_callback, NULL);
	char lockout;

	while (running) {
		lockout = 0;
		score += clear_rows(&board);

		if (hit_side(x, y, &held, &board))
			x = last_x;

		if (hit_floor(x, y, &held, &board))
			lockout = 1;

		draw_board(&board);

		if (!game_over)
			draw_piece(x, y, held.colour, held.bitmap);

		char score_string[16];
		snprintf(score_string, sizeof(score_string), "Score: %d", score);
		score_string[sizeof(score_string) - 1] = '\0';
		plot_text(score_string, font, ((SDL_Color){255,255,255,255}), 10, 10);

		if (game_over)
			plot_text("Game over", font, ((SDL_Color){255,255,255,255}), 90, 50);

		plot_update();
		SDL_WaitEvent(&e);
		if (pause_mode) {
			if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_p) {
				pause_mode = 0;
			}
			continue;
		}

		switch (e.type) {
		case SDL_USEREVENT:
			if (lockout && !game_over) {
				drop_piece(x, y, &held, &board);
				last_x = last_y = x = y = 0;
				new_piece(&held);
				if (piece_overlaps(&held, &board, x, y)) {
					game_over = true;
				}

				lockout = 0;
			} else {
				last_y = y++; /* gravity */
				last_x = x;
			}
			break;
		case SDL_QUIT:
			fprintf(stderr, "quit\n");
			running = false;
			break;
		case SDL_KEYDOWN:
			switch (e.key.keysym.sym)
			{
			case SDLK_p: pause_mode = 1; break;
			case SDLK_a: last_x = x--; break;
			case SDLK_d: last_x = x++; break;
			case SDLK_w:
				i = 0;
				do {
					rotate(&held, 1);
				} while(hit_side(x, y, &held, &board) && i++ < 4);
				break;
			case SDLK_s:
				speed_mode = 1;
				break;
			case SDLK_q:
				running = false;
				break;
			default:
				break;
			}
			break;
		case SDL_KEYUP:
			switch (e.key.keysym.sym)
			{
			case SDLK_s:
				speed_mode = 0;
				break;
			default:
				break;
		}
		default:
			break;
		}
	}
}
コード例 #12
0
void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
{
	struct divecomputer *dc;

	if (d)
		dc = select_dc(&d->dc);

	if (!forceRedraw && dive == d && (d && dc == diveDC))
		return;

	clear();
	dive = d;
	diveDC = d ? dc : NULL;

	if (!isVisible() || !dive) {
		return;
	}

	scene()->setSceneRect(0,0, viewport()->width()-50, viewport()->height()-50);

	QSettings s;
	s.beginGroup("ProfileMap");
	QPointF toolTipPos = s.value("tooltip_position", QPointF(0,0)).toPointF();
	s.endGroup();

	toolTip = new ToolTipItem();
	toolTip->setPos(toolTipPos);

	scene()->addItem(toolTip);

	// Fix this for printing / screen later.
	// plot_set_scale(scale_mode_t);

	if (!dc->samples) {
		static struct sample fake[4];
		static struct divecomputer fakedc;
		fakedc = dive->dc;
		fakedc.sample = fake;
		fakedc.samples = 4;

		/* The dive has no samples, so create a few fake ones.  This assumes an
		ascent/descent rate of 9 m/min, which is just below the limit for FAST. */
		int duration = dive->dc.duration.seconds;
		int maxdepth = dive->dc.maxdepth.mm;
		int asc_desc_time = dive->dc.maxdepth.mm*60/9000;
		if (asc_desc_time * 2 >= duration)
			asc_desc_time = duration / 2;
		fake[1].time.seconds = asc_desc_time;
		fake[1].depth.mm = maxdepth;
		fake[2].time.seconds = duration - asc_desc_time;
		fake[2].depth.mm = maxdepth;
		fake[3].time.seconds = duration * 1.00;
		fakedc.events = dc->events;
		dc = &fakedc;
	}

	/*
	 * Set up limits that are independent of
	 * the dive computer
	 */
	calculate_max_limits(dive, dc, &gc);

	QRectF profile_grid_area = scene()->sceneRect();
	gc.maxx = (profile_grid_area.width() - 2 * profile_grid_area.x());
	gc.maxy = (profile_grid_area.height() - 2 * profile_grid_area.y());

	/* This is per-dive-computer. Right now we just do the first one */
	gc.pi = *create_plot_info(dive, dc, &gc);

	/* Depth profile */
	plot_depth_profile();

	plot_events(dc);

	/* Temperature profile */
	plot_temperature_profile();

	/* Cylinder pressure plot */
	plot_cylinder_pressure(dive, dc);

	/* Text on top of all graphs.. */
	plot_temperature_text();

	plot_depth_text();

	plot_cylinder_pressure_text();

	plot_deco_text();

	/* Bounding box */
	QPen pen = defaultPen;
	pen.setColor(profile_color[TIME_GRID].at(0));
	QGraphicsRectItem *rect = new QGraphicsRectItem(profile_grid_area);
	rect->setPen(pen);
	scene()->addItem(rect);

	/* Put the dive computer name in the lower left corner */
	QString nick(get_dc_nickname(dc->model, dc->deviceid));
	if (nick.isEmpty())
		nick = QString(dc->model);

	if (nick.isEmpty())
		nick = tr("unknown divecomputer");

	gc.leftx = 0; gc.rightx = 1.0;
	gc.topy = 0; gc.bottomy = 1.0;

	text_render_options_t computer = {DC_TEXT_SIZE, TIME_TEXT, LEFT, TOP};
	diveComputer = plot_text(&computer, QPointF(gc.leftx, gc.bottomy), nick);
	// The Time ruler should be right after the DiveComputer:
	timeMarkers->setPos(0, diveComputer->y());

	if (PP_GRAPHS_ENABLED) {
		plot_pp_gas_profile();
		plot_pp_text();
	}


	/* now shift the translation back by half the margin;
	 * this way we can draw the vertical scales on both sides */
	//cairo_translate(gc->cr, -drawing_area->x / 2.0, 0);

	//gc->maxx += drawing_area->x;
	//gc->leftx = -(drawing_area->x / drawing_area->width) / 2.0;
	//gc->rightx = 1.0 - gc->leftx;

	plot_depth_scale();

#if 0
	if (gc->printer) {
		free(pi->entry);
		last_pi_entry = pi->entry = NULL;
		pi->nr = 0;
	}
#endif

	QRectF r = scene()->itemsBoundingRect();
	scene()->setSceneRect(r.x() - 15, r.y() -15, r.width() + 30, r.height() + 30);
	if (zoomLevel == 0) {
		fitInView(sceneRect());
	}
}