Development/Tutorials/Introduction to Goya usage: Difference between revisions

From KDE TechBase
(Mark for archiving)
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{TutorialBrowser|
{{Archived}}


series=Goya Framework|
name=Introduction to the Goya Framework usage|
pre=[http://mindview.net/Books/TICPP/ThinkingInCPP2e.html C++], [http://www.trolltech.com/products/qt/ Qt], [http://doc.trolltech.com/latest/model-view-programming.html Model/View Qt Framework], [[Getting_Started/Build/KDE4|KDE4 development environment]]|
next=[[Development/Tutorials/Introduction to Goya usage 2|A slightly more complex example]]
|
}}
==Abstract==
==Abstract==
We are developing some component of our application using Model/View (check prerequisites). At some point on our development, we discover that we actually want to add widgets to our delegate, but the Model/View framework does not provide a powerful and integrated way of doing so. Here is where Goya comes to help out for this task.
We are developing some component of our application using Model/View (check prerequisites). At some point on our development, we discover that we actually want to add widgets to our delegate, but the Model/View framework does not provide a powerful and integrated way of doing so. Here is where Goya comes to help out for this task.
Line 15: Line 6:
We could say Goya is a layer between the view and your delegate that draws widgets with the needed options and that seem to behave as if they were real widgets, but they are fake widgets after all.
We could say Goya is a layer between the view and your delegate that draws widgets with the needed options and that seem to behave as if they were real widgets, but they are fake widgets after all.


Goya is so nice mainly because it integrates pretty well with the Model/View design, and uses the Qt powerful signals and slots. Goya widgets will emit signals when something have happened to them, so you will be able to connect those signals to your app slots, and do fancy stuff without complex stuff.
Goya is so nice mainly because it integrates pretty well with the Model/View design, and uses the Qt powerful signals and slots. Goya widgets will emit signals when something has happened to them, so you will be able to connect those signals to your app slots, and do fancy stuff without complex stuff.
==A Simple Example==
==A Simple Example==
This example consists on a single window that will contain a list view. There will be pushbuttons only in the odd rows.
This example consists on a single window that will contain a list view. There will be pushbuttons only in the odd rows.


<code cppqt>
<syntaxhighlight lang="cpp-qt">
// Basic Goya includes
// Basic Goya includes
#include <goya/goya.h>
#include <goya/kwidgetitemdelegate.h>
#include <goya/pushbutton.h>


// Basic Qt includes
// Basic Qt includes
Line 38: Line 28:
#include <kicon.h>
#include <kicon.h>


// This is our delegate, it has to inherit KWidgetItemDelegate which inherits
// QAbstractItemDelegate. The delegate needs on its constructor first
// parameter a view, this is different to a regular QAbstractItemDelegate
// because we need to install event filters in order to allow interaction
// with the user.
class MiDelegate
class MiDelegate
     : public Goya::Canvas
     : public KWidgetItemDelegate
{
{
     Q_OBJECT
     Q_OBJECT
public:
public:
     MiDelegate(QAbstractItemView *itemView, QObject *parent = 0)
     MiDelegate(QAbstractItemView *itemView, QObject *parent = 0)
         : Canvas(itemView, parent)
         : KWidgetItemDelegate(itemView, parent)
     {
     {
        button = new Goya::PushButton(0);
        button->setText("More Information");
        button->setIcon(KIcon("help-about"));
        button->setIconSize(QSize(16, 16));
        button->setEatEvents(QEvent::MouseButtonPress);
        button->setEatEvents(QEvent::MouseButtonRelease);
        button->setEatEvents(QEvent::MouseButtonDblClick);
        connect(button, SIGNAL(clicked(QModelIndex,const Goya::PushButton*)),
                this, SLOT(slotClicked(QModelIndex)));
     }
     }


     virtual ~MiDelegate()
     virtual ~MiDelegate()
     {
     {
        delete button;
     }
     }


     QList<Goya::Widget*> widgetsForIndex(const QModelIndex &index) const
     QList<QWidget*> createItemWidgets() const
     {
     {
         if (index.row() % 3)
         return QList<QWidget*>() << new QPushButton();
            return QList<Goya::Widget*>();
 
        return QList<Goya::Widget*>() << button;
     }
     }


     QPoint widgetPosition(Goya::Widget *widget, const QStyleOption *option,
     void initializeItemWidgets(const QList<QWidget*> widgets,
                          const QModelIndex &index) const
                              const QStyleOptionViewItem &option,
                              const QModelIndex &index) const
     {
     {
         return QPoint(option->fontMetrics.height(),
         QPushButton *button = static_cast<QPushButton*>(widgets.at(0));
                      option->fontMetrics.height());
        button->setText("More Information");
        button->setIcon(KIcon("help-about"));
        button->setIconSize(QSize(16, 16));
 
        connect(button, SIGNAL(clicked(QModelIndex,const Goya::PushButton*)),
                this, SLOT(slotClicked(QModelIndex)));
     }
     }


Line 104: Line 89:
         painter->restore();
         painter->restore();


         Canvas::paint(painter, option, index);
         KWidgetItemDelegate::paintWidgets(painter, option, index);
     }
     }


     QSize sizeHint(const QStyleOptionViewItem &option,
     QSize sizeHint() const
                  const QModelIndex &index) const
     {
     {
         Q_UNUSED(option);
         return QSize(600, 60);
        Q_UNUSED(index);
 
        QSize size = Canvas::sizeHint(option, index);
 
        size.setWidth(size.width() + option.fontMetrics.height() * 4);
        size.setHeight(size.height() + option.fontMetrics.height() * 4);
 
        return size;
     }
     }
private:
    Goya::PushButton *button;


private Q_SLOTS:
private Q_SLOTS:
Line 144: Line 117:
                         ki18n("A test for the Goya subsystem"),
                         ki18n("A test for the Goya subsystem"),
                         "http://www.ereslibre.es",
                         "http://www.ereslibre.es",
                         "ereslibre@kde.org");
                         "konqui@konqui.org");


     KCmdLineArgs::init(argc, argv, &aboutData);
     KCmdLineArgs::init(argc, argv, &aboutData);
Line 198: Line 171:


#include "main.moc"
#include "main.moc"
</code>
</syntaxhighlight>

Latest revision as of 12:45, 31 May 2019


This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.

Abstract

We are developing some component of our application using Model/View (check prerequisites). At some point on our development, we discover that we actually want to add widgets to our delegate, but the Model/View framework does not provide a powerful and integrated way of doing so. Here is where Goya comes to help out for this task.

We could say Goya is a layer between the view and your delegate that draws widgets with the needed options and that seem to behave as if they were real widgets, but they are fake widgets after all.

Goya is so nice mainly because it integrates pretty well with the Model/View design, and uses the Qt powerful signals and slots. Goya widgets will emit signals when something has happened to them, so you will be able to connect those signals to your app slots, and do fancy stuff without complex stuff.

A Simple Example

This example consists on a single window that will contain a list view. There will be pushbuttons only in the odd rows.

// Basic Goya includes
#include <goya/kwidgetitemdelegate.h>

// Basic Qt includes
#include <QPainter>
#include <QBoxLayout>
#include <QListView>
#include <QStringListModel>

// Basic KDE includes
#include <kapplication.h>
#include <kaboutdata.h>
#include <kmessagebox.h>
#include <kcmdlineargs.h>
#include <klocalizedstring.h>
#include <kicon.h>

// This is our delegate, it has to inherit KWidgetItemDelegate which inherits
// QAbstractItemDelegate. The delegate needs on its constructor first
// parameter a view, this is different to a regular QAbstractItemDelegate
// because we need to install event filters in order to allow interaction
// with the user.
class MiDelegate
    : public KWidgetItemDelegate
{
    Q_OBJECT
public:
    MiDelegate(QAbstractItemView *itemView, QObject *parent = 0)
        : KWidgetItemDelegate(itemView, parent)
    {
    }

    virtual ~MiDelegate()
    {
    }

    QList<QWidget*> createItemWidgets() const
    {
        return QList<QWidget*>() << new QPushButton();
    }

    void initializeItemWidgets(const QList<QWidget*> widgets,
                               const QStyleOptionViewItem &option,
                               const QModelIndex &index) const
    {
        QPushButton *button = static_cast<QPushButton*>(widgets.at(0));
        button->setText("More Information");
        button->setIcon(KIcon("help-about"));
        button->setIconSize(QSize(16, 16));

        connect(button, SIGNAL(clicked(QModelIndex,const Goya::PushButton*)),
                this, SLOT(slotClicked(QModelIndex)));
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const
    {
        if (option.state & QStyle::State_Selected)
        {
            painter->fillRect(option.rect, option.palette.highlight());
        }

        painter->save();

        if (option.state & QStyle::State_Selected)
        {
            painter->setPen(QPen(option.palette.highlightedText().color()));
        }

        painter->drawText(option.fontMetrics.height() + option.rect.left(),
                          option.fontMetrics.height() * 3 + 
                          Canvas::sizeHint(option, index).height() +
                          option.rect.top(),
                          QString("This is the index in row number ") + 
                          QString::number(index.row() + 1));

        painter->restore();

        KWidgetItemDelegate::paintWidgets(painter, option, index);
    }

    QSize sizeHint() const
    {
        return QSize(600, 60);
    }

private Q_SLOTS:
    void slotClicked(const QModelIndex &index)
    {
        KMessageBox::information(0, "More information clicked on row " + 
                                 QString::number(index.row() + 1),
                                 "Button clicked");
    }
};

int main(int argc, char **argv)
{
    KAboutData aboutData("goyatest",
                         0,
                         ki18n("Goya Test "),
                         "1.0",
                         ki18n("A test for the Goya subsystem"),
                         KAboutData::License_LGPL,
                         ki18n("(c) Rafael Fernández López, 2007"),
                         ki18n("A test for the Goya subsystem"),
                         "http://www.ereslibre.es",
                         "[email protected]");

    KCmdLineArgs::init(argc, argv, &aboutData);
    KApplication app;

    QWidget *widget = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout;

    widget->setLayout(layout);
    widget->resize(800, 600);

    QListView *listView = new QListView();
    listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    QStringListModel *model = new QStringListModel();
    MiDelegate *delegate = new MiDelegate(listView);

    QListView *listView2 = new QListView();
    listView2->setSelectionMode(QAbstractItemView::ExtendedSelection);
    QStringListModel *model2 = new QStringListModel();
    MiDelegate *delegate2 = new MiDelegate(listView2);

    model->insertColumn(0);
    for (int i = 0; i < 1000; ++i)
    {
        model->insertRow(i);
        model->setData(model->index(i, 0), QString::number(i));
    }

    model2->insertColumn(0);
    for (int i = 0; i < 10; ++i)
    {
        model2->insertRow(i);
        model2->setData(model2->index(i, 0), QString::number(i));
    }

    listView->setModel(model);
    listView->setItemDelegate(delegate);
    listView->setVerticalScrollMode(QListView::ScrollPerPixel);

    listView2->setModel(model2);
    listView2->setItemDelegate(delegate2);
    listView2->setVerticalScrollMode(QListView::ScrollPerPixel);

    layout->addWidget(new QPushButton("Above Button"));
    layout->addWidget(listView);
    layout->addWidget(listView2);
    layout->addWidget(new QPushButton("Below Button"));

    widget->show();

    return app.exec();
}

#include "main.moc"