Ejemplo n.º 1
0
void CalendarWidget::calculateAndDrawMonth(int j_y, int j_m, int j_d)
{
    monthPixmap = QPixmap(this->size());

    //Must be done.
    //`Qt::transparent` is equivalent to `QColor::fromRgb(0,0,0,0)` or `QColor::fromRgba(0)`.
    //We could also have used `palette().color(QPalette::Window)`.
    monthPixmap.fill(Qt::transparent);

    QPainter p(&monthPixmap);
    QPen blackPen(QColor(0, 0, 0));
    QPen grayPen(QColor(192, 192, 192));
    QPen blueThickPen(QColor(0, 0, 255), 2);

    p.setPen(blackPen);

    int hUnit = this->width() / 7;
    int vUnit = this->height() / 7;

    QString title = Ct::Date::PersianDate::nameOfMonth(j_m) + " " + QString::number(j_y);
    QRect titleRect(0, 0, this->width(), vUnit);
    titleRect.adjust(1, 1, -1, -1);
    p.fillRect(titleRect, QColor(64, 128, 255));
    QFont boldFont = this->font();
    boldFont.setBold(true);
    p.setFont(boldFont);
    p.drawText(titleRect, Qt::AlignCenter, title);

    for (int i = 0; i < 7; i++)
    {
        QRect cellRect((6 - i) * hUnit, vUnit, hUnit, vUnit);
        cellRect.adjust(1, 1, -1, -1);
        if (i == 6)
            p.fillRect(cellRect, QColor(96, 160, 255));
        else
            p.fillRect(cellRect, QColor(128, 192, 255));
        p.drawText(cellRect, Qt::AlignCenter, Ct::Date::PersianDate::nameOfPersianWeekDay(i + 1));

        for (int j = 0; j < 7; j++)
            datestamps[j][i] = 0;
    }

    QDate firstDayOfJalaliMonth;
    Ct::Date::PersianDate::JalaliToGregorian(firstDayOfJalaliMonth, j_y, j_m, 1);

    //Without the QTime of 12 P.M, we got problems on 26/27 Esfand 1391 = 16/17 March 2013:
    //  Both shows the same date! This was on Win7. On WinXP it was on the same month at different
    //  days and in linux I did not test.
    QDateTime dateStamp(firstDayOfJalaliMonth, QTime(12, 0, 0));

    int hPos = 0;
    int vPos = 2;

    int mapWeekStartDayFromMondayToSaturday[] = { 0, 3, 4, 5, 6, 7, 1, 2 };
    int PersianWeekStartDay = mapWeekStartDayFromMondayToSaturday[firstDayOfJalaliMonth.dayOfWeek()];
    hPos = PersianWeekStartDay - 1;

    int modFridays = (8 - PersianWeekStartDay) % 7;

    int jalaliMonthDayCount = Ct::Date::PersianDate::numberOfDaysInJalaliMonth(j_y, j_m);

    QFont smallEnglishFont("Tahoma", 8, QFont::Bold);
    for (int i = 1; i <= jalaliMonthDayCount; i++)
    {
        QRect cellRect((6 - hPos) * hUnit, vPos * vUnit, hUnit, vUnit);
        cellRect.adjust(1, 1, -1, -1);
        if (i % 7 == modFridays)
            p.fillRect(cellRect, QColor(128, 192, 255));
        else
            p.fillRect(cellRect, Qt::white);
        if (i == j_d) //Today
        {
            p.setPen(blueThickPen);
            p.drawRect(cellRect);
        }

        //Draw the Gregorian number FIRST so that it goes lower than the Persian day in high-DPI.
        if (settings.showGregorianDates)
        {
            p.setPen(grayPen);
            p.setFont(smallEnglishFont);

            QString dayText = "";
            //In case either Persian or Gregorian day is 1, we add the short month name (MMM). Since
            //  in Persian locale the month name is localized, we also add space before it to have
            //  some right margin.
            if (i == 1 || dateStamp.date().day() == 1)
                dayText = " " + dateStamp.date().toString("MMM") + " ";
            //We add space after the day because some right margin is always useful! Of course this space
            //  is used if a localized month name wasn't added to the day number.
            dayText += QString::number(dateStamp.date().day()) + " ";

            p.drawText(cellRect, Qt::AlignRight | Qt::AlignBottom, dayText);
        }

        p.setPen(blackPen);
        p.setFont(this->font());
        p.drawText(cellRect, Qt::AlignCenter, QString::number(i));

        //FIRST save the datestamps
        datestamps[(6 - hPos)][vPos] = dateStamp.toMSecsSinceEpoch();
        dateStamp = dateStamp.addDays(1);

        //THEN 'increase' hPos/vPos
        hPos++;
        if (hPos == 7)
        {
            hPos = 0;
            vPos++;

            if (vPos == 7)
                vPos = 2; //Draw the excess 30th and 31th day in the top row.
        }
    }
}
Ejemplo n.º 2
0
/*
 * Author: Csaszar, Peter <*****@*****.**>
 * Copyright (C) 2009-2012 Csaszar, Peter
 */

#include <sys/time.h>
#include <sys/stat.h>

#include <unistd.h>

#include <errno.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef FCLOG
#include <fclog.h>
#endif

#include "csjp_logger.h"

namespace csjp {

static void dateStamp(char res[16])
{
	time_t t = time(NULL);
	strftime(res, 16, "%Y-%m-%d-%a", localtime(&t));
}

static void timeStamp(char res[16])
{
	char timeStr[16] = {0};
	timeval unixTime;

	gettimeofday(&unixTime, NULL);
	time_t t = unixTime.tv_sec;
	int unixMillisecs = unixTime.tv_usec/1000;
	struct tm _tm;

	localtime_r(&t, &_tm);
	strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &_tm);
	snprintf(res, 16, "%s:%03d", timeStr, unixMillisecs);
}

static char g_LogDir[256] = {0};
static char g_LogFileName[512] = {0};
static char g_LogFileNameSpecializer[128] = {0};
static char g_BinaryName[128] = "unknown";
bool verboseMode = false;
bool haveLogDir = true;

void resetLogFileName()
{
	g_LogFileName[0] = 0;
}

void setLogDir(const char * dir)
{
	if(dir)
		strncpy(g_LogDir, dir, sizeof(g_LogDir));
	else
		strncpy(g_LogDir, "./", sizeof(g_LogDir));
	haveLogDir = true;
	resetLogFileName();
}

void setBinaryName(const char * name)
{
	if(!name)
		return;

	const char *baseName = strrchr(name, '/');
	baseName = baseName ? baseName + 1 : name;
	strncpy(g_BinaryName, baseName, sizeof(g_BinaryName));

	resetLogFileName();
}

const char * getBinaryName()
{
	return g_BinaryName;
}

const char * logFileName()
{
#ifdef FCLOG
	return FCLOG_FILE;
#else
	if(g_LogFileName[0] == 0 && haveLogDir){
		struct stat fileStat;
		if(0 <= stat(g_LogDir, &fileStat))
			if(S_ISDIR(fileStat.st_mode)){
				snprintf(g_LogFileName, sizeof(g_LogFileName),
						"%s/%s%s.log", g_LogDir,
						g_BinaryName, g_LogFileNameSpecializer);
				return g_LogFileName;
			}
		haveLogDir = false;
	}
	return g_LogFileName;
#endif
}

void setLogFileNameSpecializer(const char * str)
{
	if(str != NULL){
		g_LogFileNameSpecializer[0] = '.';
		strncpy(g_LogFileNameSpecializer + 1, str, sizeof(g_LogFileNameSpecializer) - 1);
	} else
		g_LogFileNameSpecializer[0] = 0;
	resetLogFileName();
}

static unsigned loggerMutex = 0; /* Initialized before main() */
void msgLogger(FILE * stdfile, const char * string, size_t length)
{
	if(!length)
		length = strlen(string);

	char header[64];
	{
		char time_stamp[16];
		timeStamp(time_stamp);

		char date_stamp[16];
		dateStamp(date_stamp);

		double c = (double)(clock())/(double)(CLOCKS_PER_SEC);

		snprintf(header, sizeof(header), "%14s %12s %7.3f %5d",
				date_stamp, time_stamp, c, getpid());
	}

	const char * fmt = "%s %s ";

#if ! _ISOC99_SOURCE
#error We need to use C99 for calculating printed number of characters with vsnprintf().
#endif

	/* Now lets calculate the amount of memory needed by the full log message. */
	int size = 0;
	size += strlen(fmt);
	size += sizeof(header);
	size += length;

	/* Allocate memory */
	char * msg = (char*)malloc(size);
	if(!msg){
		if(stderr)
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					"No enoguh memory for log message!");
		return;
	}

	/* Compose the log message */
	int len = snprintf(msg, size, fmt, header, string);
	if(len < 0){
		if(stderr)
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					"Failed to snprintf the log message and its header!\n");
		free(msg);
		return;
	}

	msg[len++] = '\n';
	msg[len] = 0;

	/* We need to have logging thread safe.
	 * We should not use posix mutex since that might fail, and
	 * on posix failure we should report the issue, thus call
	 * this logger. This would be a circular dependency and a
	 * possible place to have infinite recursion.
	 *
	 * So we are going to use gcc special low level atomic operations.
	 * http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html#Atomic-Builtins
	 * type __sync_fetch_and_add (type *ptr, type value, ...)
	 * type __sync_fetch_and_sub (type *ptr, type value, ...)
	 */
#if not __GNUC__ >= 4
#error "We need gcc 4 or later for __sync_fetch_and_add() and __sync_fetch_and_sub()"
#endif
	unsigned loggerMutexLast = 1;
	while(loggerMutexLast){
		loggerMutexLast = __sync_fetch_and_add(&loggerMutex, 1);
		if(loggerMutexLast){
			__sync_fetch_and_sub(&loggerMutex, 1);
			usleep(100);
		}
	}

	if(haveLogDir && logFileName()[0]){
		FILE *log = fopen(logFileName(), "a");
		if(log){
			fputs(msg, log);
			fflush(log);
			TEMP_FAILURE_RETRY( fclose(log) );
		} else if(stderr) {
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					" Could not open logfile: %s\n", logFileName());
			haveLogDir = false;
		}
	}

	basicLogger(msg, stdfile, g_BinaryName);

	__sync_fetch_and_sub(&loggerMutex, 1);

	free(msg);
}