Для Qt 4.8.5 или Qt 4.8.6.
Ох и наелся я с печатью длинных таблиц. Багов в 4.8 просто мильён.
Итак, есть длинная таблица в html. Мы подаем ее в QTextDocument через setHtml(). Затем печатаем
doc->print(printer);
1) Чтобы таблица повторяла на каждой странице заголовок нужно этот заголовок выделить тегом <thead>.
2) Это не должна быть вложенная таблица.
3) Забудьте про задний фон, не используйте bgcolor или background-color. Т.к. это чудо вполне может закрасить этим цветом шапку таблицы.
4) Не используйте valign=middle.
После этого таблица будет более менее корректно отображаться. Резать оно будет конечно от балды и возможно прям поперек слова. Но это лучше чем ничего.
четверг, 24 октября 2019 г.
вторник, 23 апреля 2019 г.
QTreeView items spacing
Как сделать отступ между элементами QTreeView?
Первый и простой способ - заюзать styleSheet.
my_tree_->setStyleSheet(".QTreeView::item{ margin: 0px 6px 6px 6px; border: 0;}");
Второй тру способ заюзать делегата.
my_tree_->setItemDelegate(new MyItemDelegate(this));
MyItemDelegate::MyItemDelegate(QObject * parent)
: QItemDelegate(parent)
{
}
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QSize sz = QItemDelegate::sizeHint(option, index);
sz.setHeight(sz.height() + 10);//накидываем 10 пикселей по 5 сверху и снизу
return sz;
}
void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV3 opt = option;
opt.rect.adjust(0, 0, -5, -5);//немножко уменьшаем размер item для отрисовки
QItemDelegate::paint(painter, opt, index);//рисуем
}
Вот таким нехитрым способом можно сделать отступы между элементами, мать их, убил на это полдня.
У QListView есть setSpacing, которого нет у QTreeView.
Первый и простой способ - заюзать styleSheet.
my_tree_->setStyleSheet(".QTreeView::item{ margin: 0px 6px 6px 6px; border: 0;}");
Второй тру способ заюзать делегата.
my_tree_->setItemDelegate(new MyItemDelegate(this));
MyItemDelegate::MyItemDelegate(QObject * parent)
: QItemDelegate(parent)
{
}
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
QSize sz = QItemDelegate::sizeHint(option, index);
sz.setHeight(sz.height() + 10);//накидываем 10 пикселей по 5 сверху и снизу
return sz;
}
void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV3 opt = option;
opt.rect.adjust(0, 0, -5, -5);//немножко уменьшаем размер item для отрисовки
QItemDelegate::paint(painter, opt, index);//рисуем
}
Вот таким нехитрым способом можно сделать отступы между элементами, мать их, убил на это полдня.
У QListView есть setSpacing, которого нет у QTreeView.
вторник, 2 апреля 2019 г.
OpenSSL https
Как добавить поддержку OpenSSL в собранную Qt.
1) Ставим OpenSSL в D:\OpenSSL.
2) configure -debug-and-release -mp -qt-zlib -qt-libjpeg -qt-libpng -opensource -platform win32-msvc2008 -openssl -I D:\OpenSSL\include -L D:\OpenSSL\lib
3) cd %QTDIR%:\src\network
4) qmake
5) nmake
В проекте:
QMAKE_LIBDIR += d:/OpenSSL/lib
LIBS += libeay32.lib ssleay32.lib crypt32.lib
INCLUDEPATH += D:/OpenSSL/include
Проверяем
#include <QSslConfiguration>
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
Должно собраться.
HTTPS запрос.
QNetworkRequest request;
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setProtocol(QSsl::TlsV1);
request.setSslConfiguration(config);
request.setUrl(url);
1) Ставим OpenSSL в D:\OpenSSL.
2) configure -debug-and-release -mp -qt-zlib -qt-libjpeg -qt-libpng -opensource -platform win32-msvc2008 -openssl -I D:\OpenSSL\include -L D:\OpenSSL\lib
3) cd %QTDIR%:\src\network
4) qmake
5) nmake
В проекте:
QMAKE_LIBDIR += d:/OpenSSL/lib
LIBS += libeay32.lib ssleay32.lib crypt32.lib
INCLUDEPATH += D:/OpenSSL/include
Проверяем
#include <QSslConfiguration>
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
Должно собраться.
HTTPS запрос.
QNetworkRequest request;
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setProtocol(QSsl::TlsV1);
request.setSslConfiguration(config);
request.setUrl(url);
QNetworkReply *netReply = netManager.get(request);
Postgres SQL
Поддержка Postgres SQL.
1) Скачиваем бинари постгреса отсюда https://www.postgresql.org/download/
2) Копируем бинари на НЖМД например сюда D:\pgsql
3) Добавляем в PATH путь D:\pgsql\bin
4) Собираем плагин в Qt
qsqlpsqld4.dll
pro файл править не надо. Используем в проекте
1) Скачиваем бинари постгреса отсюда https://www.postgresql.org/download/
2) Копируем бинари на НЖМД например сюда D:\pgsql
3) Добавляем в PATH путь D:\pgsql\bin
4) Собираем плагин в Qt
- Конфигурируем исходники и включаем нужный драйвер как plugin
configure.exe -I D:/pgsql/include -L D:/pgsql/lib -plugin-sql-psql cd src\plugins\sqldrivers\psqlqmakenmake
qsqlpsqld4.dll
pro файл править не надо. Используем в проекте
db_ = QSqlDatabase::addDatabase("QPSQL");
db_.setHostName("host");
db_.setPort(5432);
db_.setDatabaseName("bisys");
db_.setUserName("postgres");
db_.setPassword("postgres");
db_.open();
воскресенье, 10 февраля 2019 г.
MS Visual Studio и mocinclude.tmp
Если в вашем проекте больше 40 путей include, которые описаны в INCLUDEPATH, то Qt создает временный файл mocinclude.tmp, в который включает все описанные пути.
Проблема в том, что студия не совсем корректно обрабатывает этот файл. Выражается это в том, что при каждой сборке студия начинает полностью пересобирать проект вместо того, чтобы пересобрать только измененные файлы.
Чтобы не допустить создания mocinclude.tmp надо изменить в Qt файл
d:\qt\mkspecs\features\moc.prf
изменив строчку
win32:count($$list($$INCLUDEPATH), 40, >) {
Проблема в том, что студия не совсем корректно обрабатывает этот файл. Выражается это в том, что при каждой сборке студия начинает полностью пересобирать проект вместо того, чтобы пересобрать только измененные файлы.
Чтобы не допустить создания mocinclude.tmp надо изменить в Qt файл
d:\qt\mkspecs\features\moc.prf
изменив строчку
win32:count($$list($$INCLUDEPATH), 40, >) {
на
win32:count($$list($$INCLUDEPATH), 100, >) {
Таким образом мы просто увеличили количество путей с 40 до 100.
среда, 6 февраля 2019 г.
Qt Installer: удаление по маске
Qt Installer не умеет удалять файлы по маске.
Нельзя просто так взять и написать
Для Windows
Для Linux
Нельзя просто так взять и написать
component.addOperation("Execute", "rm", "-f", "files*");Это не сработает. Это обходится вызовом командного интерпретатора
Для Windows
component.addOperation("Execute", "cmd.exe", "/C", "del", "files*.*");
Для Linux
component.addOperation("Execute", "bash", "-c", "rm -f files*");Последний параметр для Linux надо писать целиком, не разделяя на части. В этом случае Qt Installer при вызове обернет команду кавычками и результат будет как если бы вы вызвали команду
bash -c "rm -f files*"
вторник, 5 февраля 2019 г.
Qt Installer: replace
Qt Installer использует скриптовый язык ECMAScript (http://doc.qt.io/qt-5/ecmascript.html)
По структуре он схож с JavaScript, но полностью они не пересекаются.
Но решения можно искать и по JavaScript.
Например, функция replace меняет только первое вхождение в строку.
var str = "bla-bla-bla";
str.replace("bla", "vobla");
Получим vobla-bla-bla.
Чтобы заменить все вхождения, надо использовать регулярку.
По структуре он схож с JavaScript, но полностью они не пересекаются.
Но решения можно искать и по JavaScript.
Например, функция replace меняет только первое вхождение в строку.
var str = "bla-bla-bla";
str.replace("bla", "vobla");
Получим vobla-bla-bla.
Чтобы заменить все вхождения, надо использовать регулярку.
str.replace(/bla/g, "vobla");
четверг, 21 апреля 2016 г.
Снова по прокрутке большой БД
Возвращаюсь к теме просмотра большой БД в виде одной большой таблицы QTableView.
Ранее я писал про извращения с наследником QTableView, теперь будем делать это каноничнее.
Итак, есть большая БД, на 100 килострок минимум. Какая БД неважно, FireBird, SQLite и т.п.
Первое, что надо сделать это определить модель.
class QueryModel : public QAbstractTableModel
и определить в ней rowCount(). rowCount() определяется так:
"SELECT COUNT(ID) FROM TABLE"
Затем в классе определяем экземпляр QSqlQuery query_, которому говорим SELECT * FROM TABLE, условно.
Далее определяем data()
QVariant QueryModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole)
{
if (query_->seek(index.row()))
{
const QSqlRecord & rec = query_->record();
Ранее я писал про извращения с наследником QTableView, теперь будем делать это каноничнее.
Итак, есть большая БД, на 100 килострок минимум. Какая БД неважно, FireBird, SQLite и т.п.
Первое, что надо сделать это определить модель.
class QueryModel : public QAbstractTableModel
и определить в ней rowCount(). rowCount() определяется так:
"SELECT COUNT(ID) FROM TABLE"
Затем в классе определяем экземпляр QSqlQuery query_, которому говорим SELECT * FROM TABLE, условно.
Далее определяем data()
QVariant QueryModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole)
{
if (query_->seek(index.row()))
{
const QSqlRecord & rec = query_->record();
QVariant val = rec.value(index.column());
QString str = val.toString();
return str;
}
}
}
Всё. Этого достаточно чтобы иметь нормально прокручиваемую таблицу.
Небольшое дополнение, не нужно вызывать функции resizeColumnsToContents() и resizeRowsToContents(), это вызовет метод data() для всех строк и получите тормоза.
среда, 14 января 2015 г.
вторник, 13 января 2015 г.
Порядок #include
Правило подключения имхо очень простое, его не сложно запомнить и не сложно ему следовать:
в файле MyClass.cpp
#include <vector> (1) сначала подключаются файлы стандартной библиотеки
#include <boost/smart_ptr.hpp> (2) затем подключатся файлы 3rd-party библиотек,
объекты и функции которых Вы используете в
своём коде
#include <MyInclude/Helpers.h> (3) свои внутренние заголовочные файлы
#include <MyClass.h> (3) свой заголовочный файл, реализацию для которого мы пишем
среда, 10 сентября 2014 г.
Тестовое задание в компанию IVIDEON
Фонарь (тестовое задание)
Требуется написать управляемый по сети фонарь. Команды управления фонарь
принимает от сервера фонаря. Предполагается, что реализация сервера уже
существует (однако недоступен вам в процессе разработки клиента фонаря).
Фонарь и сервер общаются по Протоколу Управления Фонарем, работающему поверх
соединения TCP.
Протокол Управления Фонарем (ПУФ) устроен следующим образом. Для изменения
состояния фонаря сервер передает ему команду управления. Все команды
кодируются в виде TLV (http://en.wikipedia.org/wiki/Type-length-value), при
этом поле type имеет размер 1 байт, поле length — 2 байта и поле value —
length байт. Все данные передаются по сети в Big Endian.
ПУФ версии 1 описывает три команды:
● ON (включить фонарь): type = 0x12, length = 0
● OFF (выключить фонарь): type = 0x13, length = 0
● COLOR (сменить цвет): type = 0x20, length = 3, value интерпретируется как
новый цвет фонаря в RGB.
Предполагается, что в будущих версиях ПУФ могут появляться новые команды,
однако структура TLV останется неизменной.
Реализация фонаря должна удовлетворять следующим требованиям:
1. При запуске фонарь должен запрашивать хост:порт (по умолчанию
127.0.0.1:9999), подсоединяться по TCP и после этого начать отрабатывать
протокол управления.
2. При получении данных от сервера фонарь собирает целые команды (type +
length + value) и, если type известен, обрабатывает команду, иначе молча ее
игнорирует.
3. При получении команды ON фонарь включается (отрисовку фонаря оставляем
на ваше усмотрение).
4. При получении команды OFF фонарь выключается.
5. При получении команды COLOR фонарь меняет цвет.
6. При завершении работы фонарь корректно закрывает соединение с сервером.
7. Реализация фонаря позволяет легко добавлять любые новые команды.
Проработанность обработки исключительных ситуаций (ошибки установления
соединения, обрывы соединения) — на ваше усмотрение.
Технологические требования:
1. Задание принимается в виде исходников, готовых к сборке в QtCreator или с
помощью Make-файлов под Linux.
2. Код должен быть написан по Qt Coding Style.
3. Репозиторий с кодом должен быть доступен на Bitbucket или Github.
Требуется написать управляемый по сети фонарь. Команды управления фонарь
принимает от сервера фонаря. Предполагается, что реализация сервера уже
существует (однако недоступен вам в процессе разработки клиента фонаря).
Фонарь и сервер общаются по Протоколу Управления Фонарем, работающему поверх
соединения TCP.
Протокол Управления Фонарем (ПУФ) устроен следующим образом. Для изменения
состояния фонаря сервер передает ему команду управления. Все команды
кодируются в виде TLV (http://en.wikipedia.org/wiki/Type-length-value), при
этом поле type имеет размер 1 байт, поле length — 2 байта и поле value —
length байт. Все данные передаются по сети в Big Endian.
ПУФ версии 1 описывает три команды:
● ON (включить фонарь): type = 0x12, length = 0
● OFF (выключить фонарь): type = 0x13, length = 0
● COLOR (сменить цвет): type = 0x20, length = 3, value интерпретируется как
новый цвет фонаря в RGB.
Предполагается, что в будущих версиях ПУФ могут появляться новые команды,
однако структура TLV останется неизменной.
Реализация фонаря должна удовлетворять следующим требованиям:
1. При запуске фонарь должен запрашивать хост:порт (по умолчанию
127.0.0.1:9999), подсоединяться по TCP и после этого начать отрабатывать
протокол управления.
2. При получении данных от сервера фонарь собирает целые команды (type +
length + value) и, если type известен, обрабатывает команду, иначе молча ее
игнорирует.
3. При получении команды ON фонарь включается (отрисовку фонаря оставляем
на ваше усмотрение).
4. При получении команды OFF фонарь выключается.
5. При получении команды COLOR фонарь меняет цвет.
6. При завершении работы фонарь корректно закрывает соединение с сервером.
7. Реализация фонаря позволяет легко добавлять любые новые команды.
Проработанность обработки исключительных ситуаций (ошибки установления
соединения, обрывы соединения) — на ваше усмотрение.
Технологические требования:
1. Задание принимается в виде исходников, готовых к сборке в QtCreator или с
помощью Make-файлов под Linux.
2. Код должен быть написан по Qt Coding Style.
3. Репозиторий с кодом должен быть доступен на Bitbucket или Github.
вторник, 3 сентября 2013 г.
QHuman DateEdit
QHuman DateEdit
Альтернативный компонент Qt для ввода даты. Есть возможность ввода пустой или неполной даты.Недостатки стандартного QDateEdıt
Стандартный QDateEdit не позволяет ввести неполную или пустую дату. Датой по умолчанию считается 1 января 2000 года. Нельзя очистить поле, там всегда будет 01.01.2000.
QHuman DateEdit
вторник, 2 июля 2013 г.
Компонент "Панель задач"
Наткнулся на qt-apps.org на компонент для Qt "Панель задач" (Task Panel). Подобные панели используются в проводнике Windows. По крайней мере использовались в XP, в семерке такой панели уже существенно меньше. Но тем не менее, может пригодиться.
Лицензия LGPL, то есть, можно использовать в коммерческих приложениях.
Проблем с использованием не обнаружил, единственно, что не понравилось - закругления уголков, немного подрихтовал напильником, чтобы было без сглаживания уголков.
Возможности компонента:
Лицензия LGPL, то есть, можно использовать в коммерческих приложениях.
Проблем с использованием не обнаружил, единственно, что не понравилось - закругления уголков, немного подрихтовал напильником, чтобы было без сглаживания уголков.
Возможности компонента:
- Группировка задач по блокам.
- Возможность добавить свой виджет в блок. Стандартное решение - это размещение ссылок в блоках.
- Эффекты анимации при сворачивании/разворачивании блоков.
- Возможность задать свою цветовую схему. По умолчанию предлагаются две стандартные схемы в стиле Windows XP.
среда, 6 февраля 2013 г.
Глобальный перехват событий
Если нужно поставить глобальный обработчик на все события то нужно переопределить метод
класса QApplication.
Например, если мы хотим перехватить все перемещения мышки, то нам поможет такой класс
| virtual bool | notify ( QObject * receiver, QEvent * e ) |
класса QApplication.
Например, если мы хотим перехватить все перемещения мышки, то нам поможет такой класс
class MyApp : public QApplication { public: MyApp(int & argc, char ** argv) : QApplication(argc, argv) {} virtual bool notify(QObject * receiver, QEvent * e) { if (e->type() == QEvent::MouseMove) { //обрабатываем событие } return QApplication::notify(receiver, e); } }; |
понедельник, 4 февраля 2013 г.
Отключить системную кнопку close
Отключить системную кнопку Close у окна можно установив окну флаги:
setWindowFlags(Qt::Window
| Qt::WindowMinimizeButtonHint
| Qt::WindowMaximizeButtonHint
| Qt::CustomizeWindowHint);
setWindowFlags(Qt::Window
| Qt::WindowMinimizeButtonHint
| Qt::WindowMaximizeButtonHint
| Qt::CustomizeWindowHint);
суббота, 29 декабря 2012 г.
Подключаем интерфейс в стиле Microsoft Ribbon
Впервые Microsoft анонсировала интерфейс Ribbon (что переводится как "лента") в 2007 году в новом выпуске MS Office. Новый интерфейс разительно отличался от привычных меню и тулбаров и не всем пришелся по вкусу.
У многих пользователей были трудности при переобучении, но с тех пор прошло уже много лет и пользователи как-то попривыкли к ленточному интерфейсу. Microsoft продолжает использовать риббоны в своих продуктах, в Windows 7, например, почти все стандартные приложения (MS Paint, WordPad) имеют интерфейс Ribbon.
Поэтому, чтобы быть в тренде, нужно использовать такой интерфейс в своих приложениях под Windows. Это сразу возвышает ваш программный продукт в глазах пользователей, т.к. сразу видно, что вы движетесь вперед, а не топчетесь на одном месте.
Для программистов на Qt/C++ существует готовое решение, которое называется Qtitan Ribbon devmachines.ru.
Сегодня мы будем подключать Qtitan Ribbon к нашему тестовому приложению на Qt.
суббота, 17 ноября 2012 г.
Интеграция роликов Adobe Flash/Flex в Qt приложение
В прошлый раз мы внедряли в приложение, написанное на Qt, баннер Silverlight. Мы не только отобразили баннер в десктоп-приложении, но и осуществили с ним саму тесную интеграцию:
мы смогли вызвать функцию, определенную в баннере, чтобы передать ей наше имя и,
наш интерактивный баннер смог позвать функцию, определенную в приложении и передать ему результаты голосования.
Подробнее об этом можно прочитать в предыдущем выпуске.
Что будет представлять из себя наш пример на этот раз. Мы построим интерфейс пользователя полностью на Flash, а результаты работы пользователя с интерфейсом будем передавать в Qt приложение. Второй частью нашего примера станет обратная задача - из Qt приложения мы передадим данные во Flash ролик.
четверг, 25 октября 2012 г.
Интеграция Silverlight в Qt приложения (пример использования)
В прошлой статье об интеграции Silverlight роликов в приложения на Qt, я описал библиотеку Qtitan Multimedia, с помощью которая оная интеграция и выполняется.
Ниже я приведу практический пример использования библиотеки Qtitan Multimedia.
Пример использования
В качестве примера создадим интерактивный баннер на Silverlight и подружим его с Qt приложением. Из приложения мы будем передавать наше имя в Silverlight и оно будет в нем использоваться. А в ролике мы предоставим возможность пользователю проголосовать за любимую технологию и передадим результаты голосования в приложение.
Ниже я приведу практический пример использования библиотеки Qtitan Multimedia.
Пример использования
В качестве примера создадим интерактивный баннер на Silverlight и подружим его с Qt приложением. Из приложения мы будем передавать наше имя в Silverlight и оно будет в нем использоваться. А в ролике мы предоставим возможность пользователю проголосовать за любимую технологию и передадим результаты голосования в приложение.
среда, 26 сентября 2012 г.
QZip, OSDab Zip, QuaZip и Microsoft Word 2007
Понадобилось мне тут генерить отчет в формате Microsoft Word 2007.
Файл docx это, как известно, набор xml-файлов и каталогов, пожатых zip-ом.
Ничтоже сумнящеся, пытаюсь пожать это дело OSDaB Zip - и упс. Word такой файл понимать отказывается. Далее беру QZip. Снова упс. QuaZip - ура, победа.
То есть, каталог пожатый QuaZip MS Word прекрасно читает, а остальные - увы. Версия zlib одна и та же. В чем причина я пока и не разобрался. Размер файла docx, пожатый разными zip-ами всегда разный.
До этого генерил отчеты для OpenOffice.org, там формат похож - тоже набор каталогов и xml-файлов пожатый zip. Тогда сжимал OSDaB Zip'ом и OpenOffice Writer читал такой файл без проблем.
Файл docx это, как известно, набор xml-файлов и каталогов, пожатых zip-ом.
Ничтоже сумнящеся, пытаюсь пожать это дело OSDaB Zip - и упс. Word такой файл понимать отказывается. Далее беру QZip. Снова упс. QuaZip - ура, победа.
То есть, каталог пожатый QuaZip MS Word прекрасно читает, а остальные - увы. Версия zlib одна и та же. В чем причина я пока и не разобрался. Размер файла docx, пожатый разными zip-ами всегда разный.
До этого генерил отчеты для OpenOffice.org, там формат похож - тоже набор каталогов и xml-файлов пожатый zip. Тогда сжимал OSDaB Zip'ом и OpenOffice Writer читал такой файл без проблем.
Подписаться на:
Сообщения (Atom)


