Ich werde mich nicht weiter um diesen Blog kümmern. Alle zukünftigen Posts sind auf der Hauptseite zu finden.
Über den Autor

Freunde
Tag Cloud
Ich werde mich nicht weiter um diesen Blog kümmern. Alle zukünftigen Posts sind auf der Hauptseite zu finden.
Oft sind die Standardansichten von Listen oder Tabellen nicht zu gebrauchen. Man möchte ein eigenes Listendesign verwenden. Da ich es selbst gerade für ein Projekt benötige, habe ich mal ein kleines Beispiel Projekt erstellt. Am Ende sieht das ganze dann so aus:

Bei meinem Ansatz war mir wichtig, das ich das QWidget, welches dann in der QListView angezeigt wird, im QtDesigner erstellen kann. So sieht mein Entwurf aus:
Ich habe einfach alles in zwei Dateien gepackt für dieses Beispiel. Hier nun erstmal die Header Datei.
customwidget.h
[cpp]
#ifndef _CUSTOMWIDGET_HEADER_
#define _CUSTOMWIDGET_HEADER_
#include <QtGui/QWidget>
#include <QtGui/QItemDelegate>
#include "ui_customlistviewitem.h"
/*
\class MyCustomListViewItem
*/
class MyCustomListViewItem : public QWidget
{
Q_OBJECT
public:
MyCustomListViewItem(QWidget * parent = 0, Qt::WindowFlags f = 0);
~MyCustomListViewItem();
public:
Ui::CustomListViewItemWidgetForm _ui;
};
/*
\class MyCustomListViewItem
*/
class MyCustomListViewItemDelegate : public QItemDelegate
{
public:
MyCustomListViewItemDelegate(QObject * parent = 0);
~MyCustomListViewItemDelegate();
virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
virtual QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const;
protected:
MyCustomListViewItem * _itemWidget;
};
/*
\class MyCustomListViewItem
*/
class MyListModel : public QAbstractListModel
{
public:
MyListModel(QObject * parent = 0);
~MyListModel();
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
};
/*
\class MyCustomListViewItem
*/
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0, Qt::WindowFlags f = 0);
~MyWidget();
};
#endif
[/cpp]
Die *.cpp Datei enthält nun die komplette Implementierung.
customwidget.cpp
[cpp]
#include "customwidget.h"
#include <QtGui/QBoxLayout>
#include <QtGui/QListView>
#include <QtGui/QPainter>
/*
\class MyCustomListViewItem
*/
MyCustomListViewItem::MyCustomListViewItem(QWidget * parent, Qt::WindowFlags f)
:QWidget(parent, f)
{
_ui.setupUi(this);
}
MyCustomListViewItem::~MyCustomListViewItem()
{
}
/*
\class MyCustomListViewItemDelegate
*/
MyCustomListViewItemDelegate::MyCustomListViewItemDelegate(QObject * parent)
:QItemDelegate(parent)
,_itemWidget(new MyCustomListViewItem())
{
}
MyCustomListViewItemDelegate::~MyCustomListViewItemDelegate()
{
if (_itemWidget)
{
delete _itemWidget;
_itemWidget = NULL;
}
}
void MyCustomListViewItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
_itemWidget->resize(option.rect.size());
// Update data of widget here.
const QString s = index.data().toString();
const QString s2 = QString("In detail it means %1").arg(s);
_itemWidget->_ui.labelHead->setText(s);
_itemWidget->_ui.labelDescription->setText(s2);
_itemWidget->_ui.progressBar->setValue( index.row() * 2 );
// Change the background color of the widget if it is selected.
QPalette pal;
if ((option.state & QStyle::State_Selected) == QStyle::State_Selected)
{
pal.setBrush(QPalette::Window, QBrush(QColor(Qt::lightGray)));
}
else
{
pal.setBrush(QPalette::Window, QBrush(QColor(Qt::transparent)));
}
_itemWidget->setPalette(pal);
// Paint the widget now.
painter->save();
painter->translate(option.rect.topLeft());
_itemWidget->render(painter);
painter->restore();
}
QSize MyCustomListViewItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
const int width = _itemWidget->minimumWidth();
const int height = _itemWidget->height();
return QSize(width, height);
}
/*
\class MyListModel
*/
MyListModel::MyListModel(QObject * parent)
:QAbstractListModel(parent)
{
}
MyListModel::~MyListModel()
{
}
int MyListModel::rowCount(const QModelIndex & parent) const
{
return 35;
}
QVariant MyListModel::data(const QModelIndex & index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
if (role == Qt::DisplayRole)
{
const QString s = QString("Data #%1").arg(index.row());
return s;
}
return QVariant();
}
/*
\class MyWidget
*/
MyWidget::MyWidget(QWidget * parent, Qt::WindowFlags f)
:QWidget(parent, f)
{
QBoxLayout * l = new QBoxLayout(QBoxLayout::TopToBottom, this);
QListView * listView = new QListView(this);
listView->setItemDelegate(new MyCustomListViewItemDelegate());
listView->setModel(new MyListModel());
l->addWidget(listView);
setLayout(l);
resize(450, 300);
}
MyWidget::~MyWidget()
{
}
[/cpp]
Bestimmt gibt es noch viele andere Möglichkeiten das gewünschte Ziel zu erreichen, nur das war jetzt mal mein Erster Ansatz.
Qt Version: 4.5.2 (Sollte aber auch mit neueren Versionen gehen)
Da ich keine Verwendung mehr für das SGT habe, kann man nun auf Ebay darauf bieten :-)
http://cgi.ebay.de/ws/eBayISAPI.dll?ViewItem&item=110746900278
Neulich in der Arbeit, eine E-Mails der IT-Administration:
Dear colleagues,
to ensure the best availability of our ftp-server, the machine is going down [...]
Was könnte das nur bedeuten? :P
Nach langer Wartezeit aufgrund der Feiertage halte ich nun endlich mein Samsung Galaxy Tab in der Hand. Das Gerät hat mich begeistert vom Ersten Moment in dem ich es in der Hand gehalten habe. Hier mal ein paar Bilder die das Tablet allgemein und im Größenvergleich zeigen.
Ich entschuldige mich wegen der Bildqualität, aber da ich noch keine Kamera habe musste mein Handy dafür herhalten (Nokia 5800 Express Music).
Positiv überascht hat mich die automatische Hintergrund Sychronisierung von meinen Google Bildern, Kontakten und Terminen. Hier wurde eine wirklich super nahtlose Integrierung eingebaut. Vorrausgesetzt hierfür ist natürlich das man die Google-Services benutzt.
Der E-Mail Client lässt nicht viel zu wünschen übrig. Ich habe 2 IMAP und 1 Microsoft Exchange Konto eingerichtet. Bei allen Konten kann einzeln angegeben werden was gesynched werden soll (E-Mails, Kontakte, Kalendar). In der E-Mail Übersicht kann man dann auswählen ob man eine All-In-One Ansicht haben möchte oder lieber jedes Konto einzeln sehen will. Einziges Manko was ich am E-Mail Client zu bemängeln habe: Man kann keinen Text aus den E-Mails in die Zwischenablage kopieren. Allerdings bin ich mir ziemlich sicher, dass das noch über ein Update folgen wird.
Zur Größe…
Für meine Zwecke ist diese absolut perfekt, auch wenn ich Anfangs etwas anderes gedacht habe. Es ist einfach zu transportieren und stellt dennoch jede Webseite perfekt da. (Auch Flash-Webseiten *hust-und-zu-iPad-guck*). Das iPad wäre für mich zu groß und vorallem zu schwer. Allzulange kann man das iPad nicht halten und sollte es, wenn man gerade auf der Couch liegt immer auf seinen Beinen abstützen. Das SGT kann man im Gegensatz dazu auch super im stehen oder laufen bedienen, was bei mir wichtig ist, da ich das SGT immer dabei habe.
Für mich ist das Samsung Galaxy Tab ein echter All-Rounder. Es ist super auf der Couch zum surfen oder chatten mit Freunden sowie für Unterwegs um seine E-Mails und Termine zu verwalten oder was für manch andere vielleicht auch wichtig sein mag: “Ständig im Facebook online sein!”
Eine Freundin hat mich heute angeschrieben wegen eines Problems. Sie hatte ein Formuar vom Bayrischen Rundfunk als PDF heruntergeladen und wollte dieses nun ausfüllen. Nun haben aber die Ersteller (bestimmt hochgradige Informatiker) des PDF’s nicht mit gedacht und keine Formfelder in dieses Dokument eingebaut. Wäre ja zu einfach… Man soll es aber digital am Computer ausfüllen.
Wie soll ein “normaler” Anwender nun so ein PDF am PC ausfüllen?
Erste logische Schlussfolgerung:
“Mal eben fix in Word importieren…” Ha! nix da, sowas geht nicht.
Zweite Idee:
Dann suchen wir uns eben einen Online Service oder ein Programm welches ein PDF Dokument nach Word konvertiert. Durch Google habe ich ganz schnell einiges dazu gefunden und ausprobiert…
An dieser Stelle möchte ich eben etwas vom Weg kommen und einen Gedanken an die Entwickler solcher Services/Programme richten:
Testet ihr das auch mit Dokumenten in denen mehr als “Hallo Welt!” (in Arial, Schriftgröße 12) drin steht? Entschuldigt, aber wenn ich sowas schon anbiete wo ich ggfs. sogar noch meine E-Mail Adresse für nachfolgenden Spam angeben muss der mich anschließend bis an mein Lebensende nervt, dann sollte man auch dafür Sorge tragen dass so ein Service funktioniert und nicht irgendeinen Wirren Schwachsinn zurück liefert.
Dritte und letztendliche Lösungsidee:
Ich habe ein Screenshot davon gemacht und habe es sie per Paint mit Textfeldern ausfüllen lassen.
Meine Bitte:
Sollte jemand ein Programm/Service kennen, das vernüftig funktioniert… her damit!
Nicht zuletzt natürlich an den Bayrischen Rundfunk: “Bitte, bitte fügt Formularfelder in dieses Dokument!”
Nun warte ich wirklich schon seit langem darauf das eine alternative zum blöden iPad von A* herauskommt. Das Samsung Galaxy Tab habe ich sofort ins Auge genommen, aber als ich dann den Preis gesehen habe und mir Details dazu durchgelesen habe stand sofort fest: Das Ding ist einfach viel zu teuer!
Nun bin ich generell wirklich niemand der nicht mal gerne Geld für solche Sachen ausgibt, aber auch das muss in einem gewissen Rahmen bleiben. Natürlich kann man jetzt sagen dass das Samsung Galaxy Tab weit aus mehr kann mit seinen zwei Kameras, dem GSM Modul und einem USB Slot (ein für A* wohl noch unbekanntes Bauteil), dennoch ist es zu teuer, für ein 7 Zoll Tablet.
Vor kurzem habe ich auch gelesen, dass Samsung das Tablet auch im 10 Zoll Format (siehe Bild) herausbringen wird (2011). Das in meinen Augen deprimierende daran ist nur, das die 10 Zoll Fläche schlecht aufgeteilt wurde. Samsung hat anscheinend beschlossen einfach ein bisschen in die Höhe zu gehen und das Tablet damit zu strecken… Wieso macht Samsung es der in der Beziehung leider viel zu guten Firma A* nicht nach und macht es fast gleichseitig? Das ist doch weitaus praktischer.
Generell frage ich mich aber auch, wo bleibt nur ein “offizielles” Tablet von Google? Ich kann mir kaum vorstellen dass das Motto: “Je länger man wartet desto mehr wird verkauft” hier funktionieren wird. Ich halte das iPad für ein Top-Produkt, und ich bin davon überzeugt das es noch mehr Menschen wie mich gibt die nur auf ein vernünftiges Android Tablet warten und A* keinen Cent geben wollen. Doch auch manche iPad bzw A* verfechter werden irgendwann schwach und entscheiden sich dann letztendlich doch dafür (Ich natürlich nicht…).
A* -> steht natürlich für Apple, die es nicht verdient haben zu oft mit vollem Namen erwähnt zu werden :)
Update:
Ich konnte nicht wiederstehen… Hab mir ein Samsung Galaxy Tab bestellt und erwarte es bis zum 22.12 ;-)
Nach langer Zeit habe ich mich auch mal wieder gefangen und mache hier weiter.
Vor etwa zwei Tagen habe ich meine SpellChecker Erweiterung als Patch an das CLucene Projekt commitet in der Hoffnung dem Projekt dadurch wieder ein Stück weiter zu helfen. Vermutlich liegt die beliebteste Verwendung in einem Did you mean Feature, welches man zusätzlich zu seiner Suche anbieten kann und welches man schon von Suchmaschinen wie Google oder Bing kennt. Hier gleich mal ein grober Aufbau und wie man die Klassen richtig verwenden kann.
Vorab muss ich allerdings sagen, das ich mich immer wieder Frage, wieso sich die Entwickler dafür entschieden haben stets einen TCHAR** u.ä. anstatt eines viel leichter zu verwaltenden std::vector zu verwenden. Dennoch habe ich mich daran gehalten und bin genauso vorgegangen wie die Entwickler es wohl geplant hatten.
Als Quelle für die Erstellung eines SpellCheck Indexes wird ein Dictionary benötigt. Bisher gibt es davon zwei Implentierungen.
Hier erstmal ein Beispiel mit dem WordListDictionaryC:
[cpp]
void testSpellIndexCreation()
{
// create some words for the index.
const TCHAR **words = new const TCHAR*[9];
words[0] = L"insane";
words[1] = L"factory";
words[2] = L"administrator";
words[3] = L"development";
words[4] = L"windows";
words[5] = L"linux";
words[6] = L"professional";
words[7] = L"software";
words[8] = 0;
// create a dictionary from the words array.
WordListDictionaryC dict(words, false);
char fsdir[CL_MAX_PATH];
_snprintf(fsdir, CL_MAX_PATH, "%s/%s", "C:/temp", "test.spellindex");
// file system directory.
Directory *fsDir = FSDirectory::getDirectory(fsdir);
// create spell checker.
SpellCheckerC sc(fsDir, 0, true);
bool created = sc.createFromDictionary(dict, true);
}
[/cpp]
Man kann also sehen, das mit ziemlich wenig Aufwand bereits der Index für sein eigenes Did you mean Feature erstellt ist.
Das Suchen im Index nach eventuellen Suchwortvorschlägen gestaltet sich genauso einfach. Zusätzlich hat man hier unter anderem auch die Möglichkeit seinen eigenen String-Distance-Algorithm anzugeben (Basisklasse: StringDistanceC). Sollte kein Bedarf für einen eigenen Algorithmus bestehen, dann wird der als Standard festgelegte Levenshtein-Algorithmus angewandt um die Distanz der Worte zu berechnen.
[cpp]
void testSpellIndexSearch(CuTest *tc)
{
char fsdir[CL_MAX_PATH];
_snprintf(fsdir, CL_MAX_PATH, "%s/%s", "C:/temp", "test.spellindex");
Directory *fsDir = FSDirectory::getDirectory(fsdir);
SpellCheckerC sc(fsDir, 0, true);
const TCHAR **suggs = sc.suggestSimilar(_T("insune"), 1);
// iterate the word suggestions
int i = 0;
while (suggs[i] != NULL)
{
TCHAR *word = suggs[i]; // the suggested word "insane"
i++;
}
}
[/cpp]
Im Grundgerüst ist es das schon was zur Verwendung gemacht werden muss.
Eine komplette API Erklärung mache ich hier nicht, da ich den Code ausreichend kommentiert habe. Sobald die Daten per Repository verfügbar sind (hoffe ich zumindest ;-)) werde ich noch einen Link dazu posten. Sollte schon früher interesse daran bestehen, kann man sich die drei Patch Dateien die dazu notwendig sind hier herunterladen.
Heute habe ich per Facebook ein ziemlich cooles Video bekommen. Das vertritt genau meine Meinung. .NET suckz! :P
http://www.dailymotion.com/video/xdwk35_dylin-prestly-microsoft-net-vs-java_tech
Allerdings weis ich noch nicht so genau wie ich dazu stehe, weil Oracle das ganze jetzt in der Hand hat. Ich hoffe sehr, dass Oracle das nicht versaut.
Am Wochenende komme ich endlich wieder dazu ein bisschen an meinen CLucene Erweiterungen zu arbeiten. Anfangen werde ich wohl mit meinem bereits vorhandenem Spell-Checker. Bisher ist dieser noch fest in den Workspace von insaneFactory integriert und nun muss ich diese Klassen nur noch so abändern das diese in die Standard CLucene Bibliothek passen. Vielleicht schaffe ich es den Patch schon am Wochenende zu Ben zu schicken damit dieser dann im normalen Git Repository verfügbar ist.
Außerdem habe ich schon damit angefangen eine Utility Klasse zu schreiben damit es auch möglich ist im numerischen Bereich Suchen durchzuführen (Bsp.: X=0.342, X>=5). In der Arbeit habe ich das bereits komplett implementiert, aber da basiert das ganze noch sehr stark auf Qt und ist somit nicht für die Community zu gebrauchen.
Na mal sehen was ich so schaffe ;)