silvansky programming stuff

8Jul/110

Rambler-Contacts

Выложили свои труды на гитхаб.
А что, пусть висят!
https://github.com/Rambler-ru/Contacts

6Jul/110

static QObject

Наткнулся на интересный баг.
Если есть класс MyClass: public QObject, а потом его использовать как static MyClass object; - то сигналы и слоты в нём работать не будут. При попытке вызвать connect(this, ...) или connect(..., this) будет runtime error.
Непрятная бага, которая заставила меня поломать голову...

6Apr/110

assert

Наткнулся в коде (/src/gui/dialogs/qinputdialog.cpp):

void QInputDialog::setInputMode(InputMode mode)
{
    Q_D(QInputDialog);
 
    QWidget *widget;
 
    /*
        Warning: Some functions in QInputDialog rely on implementation details
        of the code below. Look for the comments that accompany the calls to
        setInputMode() throughout this file before you change the code below.
    */
 
    switch (mode) {
    case IntInput:
        d->ensureIntSpinBox();
        widget = d->intSpinBox;
        break;
    case DoubleInput:
        d->ensureDoubleSpinBox();
        widget = d->doubleSpinBox;
        break;
    default:
        Q_ASSERT(mode == TextInput);
        d->chooseRightTextInputWidget();
        return;
    }
 
    d->setInputWidget(widget);
}

switch просто поразил своим ассертом в default'е! )

Tagged as: , , , No Comments
5Apr/110

nine part pixmap

Код для отрисовки картинки из 9 частей (типа border-image). Принимает QImage, но может быть модифицирован для работы напрямую с QPixmap.

void drawNinePartImage(const QImage &image, QRectF paintRect, qreal borderLeft, qreal borderRight, qreal borderTop, qreal borderBottom, QPainter * painter)
{
	QPixmap bg = QPixmap::fromImage(image);
	// source size
	qreal w = bg.width();
	qreal h = bg.height();
	// target size
	qreal tw = paintRect.width();
	qreal th = paintRect.height();
/*
 
+-------+-------------------+-------+
|       |                   |       |
|   0   |         1         |   2   |
|       |                   |       |
+-------+-------------------+-------+
|       |                   |       |
|   3   |         4         |   5   |
|       |                   |       |
+-------+-------------------+-------+
|       |                   |       |
|   6   |         7         |   8   |
|       |                   |       |
+-------+-------------------+-------+
 
*/
	QPainter::PixmapFragment fragments[9]; // we'll draw 9-part pixmap
	qreal hborders = borderLeft + borderRight;
	qreal vborders = borderTop + borderBottom;
	qreal sx = (tw - hborders) / (w - hborders), sy = (th - vborders) / (h - vborders);
	qreal hbLeft = borderLeft / 2.0;
	qreal hbRight = borderRight / 2.0;
	qreal hbTop = borderTop / 2.0;
	qreal hbBottom = borderBottom / 2.0;
	fragments[0] = QPainter::PixmapFragment::create(QPointF(hbLeft, hbTop),
							QRectF(0, 0, borderLeft, borderTop));
	fragments[1] = QPainter::PixmapFragment::create(QPointF(borderLeft + (tw - hborders) / 2.0, hbTop),
							QRectF(borderLeft, 0, w - hborders, borderTop),
							sx);
	fragments[2] = QPainter::PixmapFragment::create(QPointF(tw - hbRight, hbTop),
							QRectF(w - borderRight, 0, borderRight, borderTop));
	fragments[3] = QPainter::PixmapFragment::create(QPointF(hbLeft, borderTop + (th - hborders) / 2.0),
							QRectF(0, borderTop, borderLeft, h - hborders),
							1.0,
							sy);
	fragments[4] = QPainter::PixmapFragment::create(QPointF(borderLeft + (tw - hborders) / 2.0, borderTop + (th - vborders) / 2.0),
							QRectF(borderLeft, borderTop, w - hborders, h - vborders),
							sx,
							sy);
	fragments[5] = QPainter::PixmapFragment::create(QPointF(tw - hbRight, borderTop + (th - vborders) / 2.0),
							QRectF(w - borderRight, borderTop, borderRight, h - vborders),
							1,
							sy);
	fragments[6] = QPainter::PixmapFragment::create(QPointF(hbLeft, th - hbBottom),
							QRectF(0, h - borderBottom, borderLeft, borderBottom));
	fragments[7] = QPainter::PixmapFragment::create(QPointF(borderLeft + (tw - hborders) / 2.0, th - hbBottom),
							QRectF(borderLeft, h - borderBottom, w - hborders, borderBottom),
							sx);
	fragments[8] = QPainter::PixmapFragment::create(QPointF(tw - hbRight, th - hbBottom),
							QRectF(w - borderRight, h - borderBottom, borderRight, borderBottom));
 
	painter->drawPixmapFragments(fragments, 9, bg);
}
 
Tagged as: , , , No Comments
25Mar/110

my damaged brain…

Долго мучился, пока не почитал мануалы. В нужном месте.
Оказывается, что если хочешь для прямого наследника QWidget'а установить background-image через setStyleSheet(), то надо ему переопределить paintEvent():

class MyCustomWidget : public QWidget
{
  Q_OBJECT
  // ...
}

void MyCustomWidget::paintEvent(QPaintEvent *)
{
  QStyleOption opt;
  opt.init(this);
  QPainter p(this);
  style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

* This source code was highlighted with Source Code Highlighter.

http://doc.qt.nokia.com/4.7/stylesheet-reference.html#list-of-stylable-widgets - там в самом конце.

23Dec/100

Qt + windows registry

Хороший не документированный способ работы с реестром винды из Qt.

Пример: прочитать системную переменную Path:

QSettings reg("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", QSettings::NativeFormat);
QStringList paths(reg.value("Path").toString().split(";"));
23Nov/100

QML WhealArea

источник: https://github.com/explicitcall/QMLbox
что: QML-элемент WheelArea, дополнение к стандартному MouseArea. реагирует на mouse wheel.
чтобы юзать, регистрируем и импортируем стандартным образом.

#ifndef WHEELAREA_H
#define WHEELAREA_H

#include <QDeclarativeItem>
#include <QGraphicsSceneWheelEvent>

class WheelArea : public QDeclarativeItem
{
    Q_OBJECT

public:
    explicit WheelArea(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent) {}

protected:
    void wheelEvent(QGraphicsSceneWheelEvent *event) {
        switch(event->orientation())
        {
            case Qt::Horizontal:
                emit horizontalWheel(event->delta());
                break;
            case Qt::Vertical:
                emit verticalWheel(event->delta());
                break;
            default:
                event->ignore();
                break;
        }
    }

signals:
    void verticalWheel(int delta);
    void horizontalWheel(int delta);
};

#endif // WHEELAREA_H
Tagged as: , , , No Comments
16Nov/100

qml & multiline elide

иногда нужно обрезать длинную строку и поставить в конце многоточие... для этого в QML у текста есть свойство elide. чтобы его задействовать нужно задать ширину текста.

а что если мы хотим вывести текст в 2 строки? и при этом естественно обрезать лишнее и поставить многоточие?...
тогда elide бессилен.

немного результатов моих мучений с данным вопросом: рабочая функция многострочного илайда!

сразу перейдём к коду.

Text {
    id: tempText
    visible: false
    width: parent.width
    wrapMode: Text.WordWrap
    function elideMultiline(text, font, linesCount) {
        tempText.font = font
        var l = text.length
        var s = "";
        for (var i = 0; i < linesCount; i++) {
            s += "W";
            if (i < linesCount - 1)
                s += "\n"
        }
        tempText.text = s
        var maxHeight = tempText.paintedHeight
        tempText.text = text
        while (tempText.paintedHeight > maxHeight) {
            tempText.text = text.substring(0, --l) + "..."
        }
        return tempText.text
    }
}
Text {
    id: longText
    width: parent.width
    wrapMode: Text.WordWrap
    font.pointSize: 16
    Component.onCompleted: {
        text = tempText.elideMultiline("my very-very-very-very and very long text with a lot of words in it and which i want to be correctly elided", font, 2)
    }
}

как видно из кода, создаётся дополнительный элемент Text и делается невидимым. он используется для определения размеров текста на экране. для этого элемента определяем функцию elideMultiline, в неё передаём текст, шрифт и нужное нам количество строк текста.

далее всё просто, простой линейный перебор (сокращаем строку на 1 символ, дописываем "...", проверяем, опять сокращаем.......)

в принципе всё работает, но когда нужно вызвать эту функцию много раз, получаются тормоза. как дойдут руки, переделаю из линейного поиска в метод золотого сечения.

Замечание. Почему-то не хочет работать text: elideMultiline(), поэтому используется событие готовности компонента и в нём делается присвоение. Если сделать всё же первый вариант, то всё будет тормозить и выдавать кучу предупреждений "QML Text: Binding loop detected for property "text""

Tagged as: , , , , No Comments
16Nov/100

<замазано>


тестирую тег span в HTML... не нашёл лучшего места, чем данный жж.
кстати, интересно наверное будут выглядеть посты в таком стиле. неудобочитаемые.

а если серьёзно, то нашёл интересный класс в QtDeclarative, называется QDeclarativeImageProvider. его надо наследовать, реализовать функции requestImage/requestPixmap, зарегистрировать наш провайдер в энджине (QDeclarativeEngine::addImageProvider()) и юзать из QML вот так:

Image {
    source: "image://providerName/imageName.png"
}

теперь можно динамически вставлять картинки в qml, передавая туда лишь строку с "image://...".

Tagged as: , , , No Comments
15Nov/100

qml + qt model/view

итак, теперь серьёзно о QML. загрузить в QML список элементов и отобразить их там - это конечно хорошо, но мало. предположим, у нас есть уже модель данных, сделанная на наследнике QAbstractItemModel и мы хотим отобразить элементы этой модели. причём перед отображением неплохо бы отфильтровать и отсортировать нашу модель.

C++-way: делаем наследника QAbstractItemView, делаем наследника QAbstractItemDelegate (для кастомной отрисовки), делаем наследника QSortFilterProxyModel (для фильтрации и сортировки).

QML-way: делаем наследника QSortFilterProxyModel (для фильтрации и сортировки), делаем в QML ListView (для моделей типа список), регистрируем наш фильтр в QML, назначаем list.model.

всё по прежнему остаётся просто! в принципе, надо лишь правильно создать и заполнить свою модель и прокси-модель.

Tagged as: , , , , No Comments