Пример #1
0
void SjDialog::EnsureRectDisplayVisibility(wxRect& r)
{
	// check against the available displays
	// at least a 128 x 128 pixel area should fit on any display!
	//
	// otherwise we align the rect to the primary display, in this case the
	// skin may be misaligned, however, there is no more space

	bool alignToPrimaryWorkspace = true;

	size_t displayCount = wxDisplay::GetCount(), d;
	if( displayCount > 1 )
	{
		for( d = 0; d < displayCount; d++ )
		{
			wxDisplay   currDisplay(d);
			wxRect      currDisplayRect = currDisplay.GetGeometry();

			wxRect      intersection = currDisplayRect.Intersect(r);
			if( intersection.width*intersection.height > 128*128 )
			{
				alignToPrimaryWorkspace = false;
				break; // done
			}
		}
	}

	if( alignToPrimaryWorkspace )
	{
		wxRect displRect = wxGetClientDisplayRect();

		if( r.width  > displRect.width ) r.width = displRect.width;
		if( r.height > displRect.height ) r.height = displRect.height;

		if( r.x < displRect.x ) r.x = displRect.x;
		if( r.x > displRect.x + displRect.width - r.width ) r.x = displRect.x + displRect.width - r.width;

		if( r.y < displRect.y ) r.y = displRect.y;
		if( r.y > displRect.y + displRect.height - r.height ) r.y = displRect.y + displRect.height - r.height;
	}
}
Пример #2
0
int CardSet::loadCsv(const CardDisplay& defDisplay, CsvFile& file)
{
    /*
     * This method reads Anki plain text file format:
     *  - plain text, UTF-8, BOM optional;
     *  - ignore lines starting with "#";
     *  - if first uncommented line starts with "tags:", use space-split words
     *    as additional facts;
     *  - recognize any delimiters;
     *  - use double quotes ("\"") as quote char, including quoting newline;
     *  - literal newline in field should be replaced by "<br>";
     *  - fields are interpreted as simplified HTML;
     *
     * Format is extended by following new features:
     *  - comments in format "#FCARD# <attr-name> <attr-value>" are interpreted as
     *    display attributes for following cards. Following attributes are
     *    recognized:
     *
     *      - "background <color-name>"
     *        specifies background color for cards from this set.
     *
     *      - "period <time-ms>"
     *        specifies period (in milliseconds) for which card will be shown.
     *
     *      - "split-{x|y} <width>,..."
     *        specifies horizontal or vertical split distribution.
     *
     *      - "cell <fact-index>,<cell-x>,<cell-y>,<color-name>,<font-family>,<pattern>,<stylesheet>"
     *        specifies display parameters for fact text.
     *
     *      - "protect {on|off},<keyword>,..."
     *        protects or unprotects specified keywords from further changes below that point.
     *
     *      - "include <filename>,<separator>"
     *        includes specified file; path may be relative to this file; separator
     *        may be specified as a literal character or a "#"-prefixed Unicode
     *        codepoint.
     */
    enum Keyword {
        UNKNOWN,
        BACKGROUND,
        PERIOD,
        SPLIT_X,
        SPLIT_Y,
        CELL,
        PROTECT,
        INCLUDE
    };
    static const struct KeywordDesc {
        Keyword     code;
        const char *name;
    } KEYWORD_LIST[] = {
        { BACKGROUND, "background" },
        { PERIOD,     "period"     },
        { SPLIT_X,    "split-x"    },
        { CELL,       "cell"       },
        { INCLUDE,    "include"    },
        { PROTECT,    "protect"    },
        { UNKNOWN,    0            }
    };
    QRegExp fcard("#FCARD#\\s*(\\w+)\\s+(.*)");
    fcard.setPatternSyntax(QRegExp::RegExp2);
    int cardCount = 0;
    QStringList tagSet;
    CardDisplay *display = 0;
    CardDisplay currDisplay(defDisplay);
    for (;;)
    {
        int flags = 0;
        QStringList line = file.readLine(&flags);
        if (line.isEmpty())
        {
            if (!file.lastError().isEmpty())
            {
                qWarning("ERROR: %s", qPrintable(file.lastError()));
                return -1;
            }
            return cardCount;
        }
        if (flags == CsvFile::FLAG_COMMENT)
        {
            if (fcard.exactMatch(line.first()))
            {
                QString aname = fcard.cap(1);
                QString aval = fcard.cap(2);
                QStringList alist;
                int ret;
                if ((ret = TextConv::smartSplit(alist, aval)) != 0)
                {
                    qWarning("ERROR: Field-list syntax error in '%s' near offset %d",
                             qPrintable(aval), ret - 1);
                    continue;
                }
                Keyword code = UNKNOWN;
                for (const KeywordDesc *kwd = KEYWORD_LIST; kwd->name != 0; kwd++)
                    if (aname == kwd->name)
                    {
                        code = kwd->code;
                        break;
                    }
                if (currDisplay.isProtected(code))
                    continue;
                switch (code)
                {
                case UNKNOWN:
                    break;
                case BACKGROUND:
                    {
                        QColor bgd = QColor(aval.trimmed());
                        if (bgd.isValid())
                            currDisplay.setBackground(bgd);
                    }
                    break;
                case PERIOD:
                    {
                        bool ok = false;
                        int period = aval.toInt(&ok);
                        if (ok &&
                                period >= CardDisplay::MIN_PERIOD &&
                                period <= CardDisplay::MAX_PERIOD)
                            currDisplay.setPeriod(period);
                    }
                    break;
                case SPLIT_X:
                case SPLIT_Y:
                    {
                        QList<int> spl;
                        bool ok = TextConv::toIntList(alist, spl);
                        if (ok && !spl.isEmpty())
                        {
                            if (code == SPLIT_X)
                                currDisplay.setSplitX(spl);
                            else
                                currDisplay.setSplitY(spl);
                        }
                    }
                    break;
                case CELL:
                    if (!alist.isEmpty())
                    {
                        QString indVal = alist.takeFirst();
                        bool ok = false;
                        int ind = indVal.toInt(&ok);
                        if (ok && ind >= 0)
                        {
                            CardCell cell;
                            cell.assign(alist);
                            currDisplay.setValue(ind, cell);
                        }
                    }
                    break;
                case PROTECT:
                    if (!alist.isEmpty())
                    {
                        QString bVal = alist.takeFirst();
                        bool value;
                        if (bVal == "on")
                            value = true;
                        else if (bVal == "off")
                            value = false;
                        else
                            break;
                        foreach (QString name, alist)
                        {
                            for (const KeywordDesc *kwd = KEYWORD_LIST; kwd->name != 0; kwd++)
                                if (name == kwd->name && kwd->code != PROTECT)
                                {
                                    currDisplay.setProtected(kwd->code, value);
                                    break;
                                }
                        }
                    }
                    break;
                case INCLUDE:
                    if (!alist.isEmpty())
                    {
                        QChar sep = CsvFile::DEFAULT_SEPARATOR;
                        if (alist.size() > 1)
                            sep = TextConv::toChar(alist[1], sep);
                        CsvFile inclFile(alist[0], sep);
                        int inclCnt = loadCsv(currDisplay, inclFile);
                        if (inclCnt < 0)
                            return inclCnt;
                        cardCount += inclCnt;
                    }
                    break;
                }
            }
            continue;
        }