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. } } }
/* * 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); }