/*************************************************************************** CIconView.cpp The IconView class (c) 2000-2007 Benoit Minisini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************/ #define __CICONVIEW_CPP #include #include #include #include #include #if QT_VERSION >= 0x030200 #include #else #include #endif #include "gambas.h" #include "CWidget.h" #include "CPicture.h" #include "CIconView.h" #include "CConst.h" DECLARE_EVENT(EVENT_Select); /* selection change */ DECLARE_EVENT(EVENT_Click); /* simple click */ DECLARE_EVENT(EVENT_Activate); /* double click */ DECLARE_EVENT(EVENT_Rename); DECLARE_EVENT(EVENT_Cancel); DECLARE_EVENT(EVENT_Compare); static int _selection_mode[] = { SELECT_NONE, QIconView::NoSelection, SELECT_SINGLE, QIconView::Single, SELECT_MULTIPLE, QIconView::Extended, CONST_MAGIC }; /*************************************************************************** class MyIconViewItem ***************************************************************************/ void MyIconViewItem::initData(void) { picture = NULL; key = NULL; } MyIconViewItem::MyIconViewItem(QIconView *parent) : QIconViewItem(parent, " ") { initData(); } MyIconViewItem::MyIconViewItem(QIconView *parent, MyIconViewItem *after) : QIconViewItem(parent, after) { initData(); } MyIconViewItem::~MyIconViewItem() { //CIconView *ob = (CIconView *)CWidget::get(listView()); //if (ob->item == this) // ob->item = NULL; if (container->item == this) container->item = NULL; if (container->save == this) container->save = NULL; container->dict->remove(key); GB.Unref(POINTER(&picture)); GB.FreeString(&key); } void MyIconViewItem::setPicture(GB_OBJECT *pict) { SET_PIXMAP(setPixmap, &picture, pict); } int MyIconViewItem::compare(QIconViewItem *i) const { int ret; if (!GB.CanRaise(container, EVENT_Compare)) ret = QIconViewItem::compare(i); else { container->compare = 0; GB.Raise(container, EVENT_Compare, 2, GB_T_STRING, key, 0, GB_T_STRING, ((MyIconViewItem *)i)->key, 0); ret = container->compare; } if (!container->asc) ret = (-ret); return ret; } /*************************************************************************** class MyIconView ***************************************************************************/ MyIconView::MyIconView(QWidget *parent) : QIconView(parent) { setMouseTracking(false); viewport()->setMouseTracking(false); setArrangementMode(QIconView::LeftToRight); setWordWrapIconText(true); setGridY(64); setSpacing(8); setGridWidth(0); } void MyIconView::startDrag() { } int MyIconView::getArrangementMode() { if (itemsMovable()) return ARRANGEMENT_FREE; else return arrangement(); } void MyIconView::setArrangementMode(int arr) { if (arr == ARRANGEMENT_FREE) { setItemsMovable(true); setAutoArrange(false); setResizeMode(QIconView::Fixed); } else { void *_object = CWidget::get(this); setAutoArrange(true); setItemsMovable(false); setArrangement((QIconView::Arrangement)arr); if (THIS->sorted) sort(THIS->asc); setResizeMode(QIconView::Adjust); arrangeItemsInGrid(true); } } void MyIconView::setGridWidth(int w) { if (w <= 0) w = 0; _grid_width = w; if (w == 0) setGridX(192); else setGridX(w * MAIN_scale); if (!itemsMovable()) arrangeItemsInGrid(true); } /*************************************************************************** IconView ***************************************************************************/ BEGIN_METHOD(CICONVIEW_new, GB_OBJECT parent) MyIconView *wid = new MyIconView(QCONTAINER(VARG(parent))); QObject::connect(wid, SIGNAL(selectionChanged()), &CIconView::manager, SLOT(selected())); QObject::connect(wid, SIGNAL(doubleClicked(QIconViewItem *)), &CIconView::manager, SLOT(activated(QIconViewItem *))); QObject::connect(wid, SIGNAL(clicked(QIconViewItem *)), &CIconView::manager, SLOT(clicked(QIconViewItem *))); QObject::connect(wid, SIGNAL(itemRenamed(QIconViewItem *)), &CIconView::manager, SLOT(renamed(QIconViewItem *))); CWIDGET_new(wid, (void *)_object); THIS->dict = new QAsciiDict; THIS->sorted = false; THIS->asc = true; THIS->item = NULL; THIS->save = NULL; THIS->editable = false; END_METHOD BEGIN_METHOD_VOID(CICONVIEW_free) delete THIS->dict; //CALL_METHOD_VOID(CWIDGET_delete); END_METHOD BEGIN_METHOD_VOID(CICONVIEW_clear) THIS->dict->clear(); WIDGET->clear(); END_METHOD BEGIN_METHOD(CICONVIEW_add, GB_STRING key; GB_STRING text; GB_OBJECT picture; GB_STRING after) MyIconViewItem *item; QIconView *wid = WIDGET; char *key = GB.ToZeroString(ARG(key)); MyIconViewItem *after = NULL; char *akey; if (*key == 0) { GB.Error("Null key"); return; } item = (*THIS->dict)[key]; if (item != NULL) { GB.Error("Key already used"); return; } if (!MISSING(after)) { akey = GB.ToZeroString(ARG(after)); if (*akey) { after = (*THIS->dict)[akey]; if (after == NULL) { GB.Error("After item does not exist"); return; } } } if (after == NULL) item = new MyIconViewItem(wid); else item = new MyIconViewItem(wid, after); item->setText(QSTRING_ARG(text)); GB.StoreString(ARG(key), &item->key); THIS->dict->insert(item->key, item); if (!MISSING(picture)) item->setPicture(ARG(picture)); item->container = THIS; item->setRenameEnabled(THIS->editable); THIS->item = item; RETURN_SELF(); END_METHOD BEGIN_METHOD(CICONVIEW_remove, GB_STRING key) MyIconViewItem *item; char *key = GB.ToZeroString(ARG(key)); item = CIconView::getItem(THIS, key); if (!item) return; delete item; END_METHOD BEGIN_METHOD(CICONVIEW_exist, GB_STRING key) GB.ReturnBoolean((*THIS->dict)[GB.ToZeroString(ARG(key))] != 0); END_METHOD BEGIN_METHOD(CICONVIEW_get, GB_STRING key) MyIconViewItem *item; char *key = GB.ToZeroString(ARG(key)); item = CIconView::getItem(THIS, key); if (!item) return; THIS->item = item; RETURN_SELF(); END_METHOD BEGIN_PROPERTY(CICONVIEW_mode) if (READ_PROPERTY) GB.ReturnInteger(CCONST_convert(_selection_mode, WIDGET->selectionMode(), SELECT_NONE, false)); else WIDGET->setSelectionMode((QIconView::SelectionMode)CCONST_convert(_selection_mode, VPROP(GB_INTEGER), SELECT_NONE, true)); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_current) MyIconViewItem *item = (MyIconViewItem *)(WIDGET->currentItem()); THIS->item = item; if (item == 0) GB.ReturnNull(); else RETURN_SELF(); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_key) MyIconViewItem *item = (MyIconViewItem *)(WIDGET->currentItem()); THIS->item = item; if (item == 0) GB.ReturnNull(); else GB.ReturnString(item->key); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_item) if (THIS->item == 0) GB.ReturnNull(); else RETURN_SELF(); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_available) GB.ReturnBoolean(THIS->item != 0); END_PROPERTY BEGIN_METHOD(CICONVIEW_find, GB_INTEGER x; GB_INTEGER y) QPoint p(VARG(x), VARG(y)); MyIconViewItem *item; WIDGET->viewport()->mapFrom(WIDGET, p); item = (MyIconViewItem *)WIDGET->findItem(p); THIS->item = item; GB.ReturnBoolean(THIS->item == 0); END_METHOD static void set_sorting(void *_object, bool sorted, bool asc) { if (sorted == THIS->sorted && asc == THIS->asc) return; THIS->sorted = sorted; THIS->asc = asc; //qDebug("setSorting(%s, %s)", THIS->sorted ? "true" : "false", THIS->asc ? "true" : "false"); WIDGET->setSorting(THIS->sorted, THIS->asc); if (THIS->sorted) { //qDebug("sort(%s)", THIS->asc ? "true" : "false"); WIDGET->sort(); } } BEGIN_PROPERTY(CICONVIEW_sorted) if (READ_PROPERTY) GB.ReturnBoolean(THIS->sorted); else set_sorting(THIS, VPROP(GB_BOOLEAN), THIS->asc); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_editable) if (READ_PROPERTY) GB.ReturnBoolean(THIS->editable); else THIS->editable = VPROP(GB_BOOLEAN); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_ascending) if (READ_PROPERTY) GB.ReturnBoolean(THIS->asc); else set_sorting(_object, THIS->sorted, VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_count) GB.ReturnInteger(WIDGET->count()); END_PROPERTY static void return_item(void *_object, MyIconViewItem *item) { if (!item) THIS->save = THIS->item; THIS->item = item; GB.ReturnBoolean(item == 0); } BEGIN_METHOD_VOID(CICONVIEW_back) MyIconViewItem *item = THIS->save; THIS->save = 0; return_item(THIS, item); END_METHOD BEGIN_METHOD(CICONVIEW_move_to, GB_STRING key) char *key = GB.ToZeroString(ARG(key)); MyIconViewItem *item = (*THIS->dict)[key]; return_item(THIS, item); END_METHOD BEGIN_METHOD_VOID(CICONVIEW_first) return_item(THIS, (MyIconViewItem *)(WIDGET->firstItem())); END_METHOD BEGIN_METHOD_VOID(CICONVIEW_next) return_item(THIS, (MyIconViewItem *)(THIS->item->nextItem())); END_METHOD BEGIN_PROPERTY(CICONVIEW_scrollbar) //QScrollView *wid = (QScrollView *)QWIDGET(_object); int scroll; if (READ_PROPERTY) { scroll = 0; if (WIDGET->hScrollBarMode() == QScrollView::Auto) scroll += 1; if (WIDGET->vScrollBarMode() == QScrollView::Auto) scroll += 2; GB.ReturnInteger(scroll); } else { scroll = VPROP(GB_INTEGER) & 3; WIDGET->setHScrollBarMode( (scroll & 1) ? QScrollView::Auto : QScrollView::AlwaysOff); WIDGET->setVScrollBarMode( (scroll & 2) ? QScrollView::Auto : QScrollView::AlwaysOff); } END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_key) GB.ReturnString(THIS->item->key); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_picture) if (READ_PROPERTY) GB.ReturnObject(THIS->item->picture); else THIS->item->setPicture(PROP(GB_OBJECT)); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_selected) MyIconViewItem *it = THIS->item; if (READ_PROPERTY) GB.ReturnBoolean(it->isSelected()); else it->iconView()->setSelected(it, VPROP(GB_BOOLEAN), true); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_text) MyIconViewItem *it = THIS->item; if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(it->text())); else it->setText(QSTRING_PROP()); END_PROPERTY BEGIN_METHOD_VOID(CICONVIEWITEM_ensure_visible) //qDebug("ensure visible: %p", THIS->item); WIDGET->ensureItemVisible(THIS->item); END_METHOD BEGIN_METHOD_VOID(CICONVIEWITEM_delete) THIS->dict->remove(THIS->item->key); delete THIS->item; END_PROPERTY /* BEGIN_METHOD_VOID(CICONVIEWITEM_init) CLASS_Item = GB.FindClass("Item"); END_METHOD */ BEGIN_PROPERTY(CICONVIEW_client_width) GB.ReturnInteger(WIDGET->width() - WIDGET->frameWidth() * 2); END_PROPERTY BEGIN_PROPERTY(CICONVIEW_client_height) GB.ReturnInteger(WIDGET->height() - WIDGET->frameWidth() * 2); END_PROPERTY BEGIN_METHOD(CICONVIEW_select_all, GB_BOOLEAN on) if (MISSING(on) || VARG(on)) WIDGET->selectAll(true); else WIDGET->selectAll(false); END_METHOD BEGIN_PROPERTY(CICONVIEW_grid_w) if (READ_PROPERTY) GB.ReturnInteger(WIDGET->gridWidth()); else WIDGET->setGridWidth(VPROP(GB_INTEGER)); END_PROPERTY /*BEGIN_PROPERTY(CICONVIEW_grid_h) if (READ_PROPERTY) GB.ReturnInteger(WIDGET->gridY() / MAIN_scale); else { WIDGET->setGridY(VPROP(GB_INTEGER) * MAIN_scale); if (!WIDGET->itemsMovable()) WIDGET->arrangeItemsInGrid(true); } END_PROPERTY*/ /*BEGIN_PROPERTY(CICONVIEW_arrangement) if (READ_PROPERTY) GB.ReturnInteger(WIDGET->getArrangementMode()); else WIDGET->setArrangementMode(VPROP(GB_INTEGER)); END_PROPERTY*/ /*BEGIN_PROPERTY(CICONVIEW_word_wrap) if (READ_PROPERTY) GB.ReturnBoolean(WIDGET->wordWrapIconText()); else WIDGET->setWordWrapIconText(VPROP(GB_BOOLEAN)); END_PROPERTY*/ BEGIN_PROPERTY(CICONVIEW_compare) if (READ_PROPERTY) GB.ReturnInteger(THIS->compare); else THIS->compare = VPROP(GB_INTEGER); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_x) if (READ_PROPERTY) GB.ReturnInteger(THIS->item->x()); else THIS->item->move(VPROP(GB_INTEGER), THIS->item->y()); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_y) if (READ_PROPERTY) GB.ReturnInteger(THIS->item->y()); else THIS->item->move(THIS->item->x(), VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_w) GB.ReturnInteger(THIS->item->width()); END_PROPERTY BEGIN_PROPERTY(CICONVIEWITEM_h) GB.ReturnInteger(THIS->item->height()); END_PROPERTY BEGIN_METHOD(CICONVIEWITEM_move, GB_INTEGER x; GB_INTEGER y) THIS->item->move(VARG(x), VARG(y)); END_METHOD BEGIN_PROPERTY(CICONVIEWITEM_editable) if (READ_PROPERTY) GB.ReturnBoolean(THIS->item->renameEnabled()); else THIS->item->setRenameEnabled(VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_METHOD_VOID(CICONVIEWITEM_rename) THIS->item->rename(); END_METHOD /*************************************************************************** IconViewItem ***************************************************************************/ GB_DESC CIconViewItemDesc[] = { GB_DECLARE(".IconViewItem", 0), GB_VIRTUAL_CLASS(), GB_PROPERTY_READ("Key", "s", CICONVIEWITEM_key), GB_PROPERTY("Picture", "Picture", CICONVIEWITEM_picture), GB_PROPERTY("Selected", "b", CICONVIEWITEM_selected), GB_PROPERTY("Text", "s", CICONVIEWITEM_text), GB_METHOD("EnsureVisible", NULL, CICONVIEWITEM_ensure_visible, NULL), GB_METHOD("Delete", NULL, CICONVIEWITEM_delete, NULL), GB_PROPERTY("Editable", "b", CICONVIEWITEM_editable), GB_METHOD("Rename", NULL, CICONVIEWITEM_rename, NULL), GB_METHOD("MoveNext", "b", CICONVIEW_next, NULL), GB_PROPERTY("X", "i", CICONVIEWITEM_x), GB_PROPERTY("Left", "i", CICONVIEWITEM_x), GB_PROPERTY("Y", "i", CICONVIEWITEM_y), GB_PROPERTY("Top", "i", CICONVIEWITEM_y), GB_PROPERTY_READ("W", "i", CICONVIEWITEM_w), GB_PROPERTY_READ("Width", "i", CICONVIEWITEM_w), GB_PROPERTY_READ("H", "i", CICONVIEWITEM_h), GB_PROPERTY_READ("Height", "i", CICONVIEWITEM_h), GB_METHOD("Move", NULL, CICONVIEWITEM_move, "(X)i(Y)i"), GB_END_DECLARE }; /*************************************************************************** IconView ***************************************************************************/ GB_DESC CIconViewDesc[] = { GB_DECLARE("IconView", sizeof(CICONVIEW)), GB_INHERITS("Control"), GB_CONSTANT("Free", "i", ARRANGEMENT_FREE), GB_CONSTANT("Row", "i", QIconView::LeftToRight), GB_CONSTANT("Column", "i", QIconView::TopToBottom), GB_CONSTANT("LeftRight", "i", QIconView::LeftToRight), GB_CONSTANT("TopBottom", "i", QIconView::TopToBottom), GB_METHOD("_new", NULL, CICONVIEW_new, "(Parent)Container;"), GB_METHOD("_free", NULL, CICONVIEW_free, NULL), GB_PROPERTY("Mode", "i", CICONVIEW_mode), GB_PROPERTY("Sorted", "b", CICONVIEW_sorted), GB_PROPERTY("Editable", "b", CICONVIEW_editable), GB_PROPERTY("Ascending", "b", CICONVIEW_ascending), //GB_PROPERTY("Arrangement", "i", CICONVIEW_arrangement), GB_PROPERTY("GridWidth", "i", CICONVIEW_grid_w), //GB_PROPERTY("GridHeight", "i", CICONVIEW_grid_h), //GB_PROPERTY("WordWrap", "b", CICONVIEW_word_wrap), GB_PROPERTY("Border", "b", CWIDGET_border_simple), GB_PROPERTY("ScrollBar", "i", CWIDGET_scrollbar), GB_PROPERTY("Compare", "i", CICONVIEW_compare), GB_PROPERTY_READ("Count", "i", CICONVIEW_count), GB_PROPERTY_READ("Available", "b", CICONVIEW_available), GB_METHOD("MoveTo", "b", CICONVIEW_move_to, "(Key)s"), GB_METHOD("MoveFirst", "b", CICONVIEW_first, NULL), GB_METHOD("MoveNext", "b", CICONVIEW_next, NULL), GB_METHOD("MoveBack", "b", CICONVIEW_back, NULL), GB_METHOD("_get", ".IconViewItem", CICONVIEW_get, "(Key)s"), GB_METHOD("Clear", NULL, CICONVIEW_clear, NULL), GB_METHOD("Add", ".IconViewItem", CICONVIEW_add, "(Key)s(Text)s[(Picture)Picture;(After)s]"), GB_METHOD("Remove", NULL, CICONVIEW_remove, "(Key)s"), GB_METHOD("Exist", "b", CICONVIEW_exist, "(Key)s"), GB_METHOD("Find", "b", CICONVIEW_find, "(X)i(Y)i"), GB_PROPERTY_READ("Current", ".IconViewItem", CICONVIEW_current), GB_PROPERTY_READ("Key", "s", CICONVIEW_key), GB_PROPERTY_READ("Item", ".IconViewItem", CICONVIEW_item), GB_METHOD("SelectAll", NULL, CICONVIEW_select_all, "[(Select)b]"), GB_PROPERTY_READ("ClientWidth", "i", CICONVIEW_client_width), GB_PROPERTY_READ("ClientW", "i", CICONVIEW_client_width), GB_PROPERTY_READ("ClientHeight", "i", CICONVIEW_client_height), GB_PROPERTY_READ("ClientH", "i", CICONVIEW_client_height), GB_EVENT("Select", NULL, NULL, &EVENT_Select), GB_EVENT("Activate", NULL, NULL, &EVENT_Activate), GB_EVENT("Click", NULL, NULL, &EVENT_Click), GB_EVENT("Rename", NULL, NULL, &EVENT_Rename), GB_EVENT("Cancel", NULL, NULL, &EVENT_Cancel), GB_EVENT("Compare", NULL, "(Key)s(OtherKey)s", &EVENT_Compare), ICONVIEW_DESCRIPTION, GB_END_DECLARE }; /*************************************************************************** class CIconView ***************************************************************************/ CIconView CIconView::manager; MyIconViewItem *CIconView::getItem(CICONVIEW *treeview, char *key) { MyIconViewItem *item = (*treeview->dict)[key]; if (item == 0) { GB.Error("Unknown item '&1'", key); return NULL; } return item; } void CIconView::raiseEvent(int ev, QIconViewItem *it) { GET_SENDER(_object); MyIconViewItem *old = THIS->item; if (!it) it = WIDGET->currentItem(); THIS->item = (MyIconViewItem *)it; RAISE_EVENT(ev); THIS->item = old; } void CIconView::selected(void) { raiseEvent(EVENT_Select, 0); #if QT_VERSION < 0x030200 raiseEvent(EVENT_Click, 0); #endif } void CIconView::activated(QIconViewItem *it) { if (!it) return; raiseEvent(EVENT_Activate, it); } void CIconView::clicked(QIconViewItem *it) { if (!it) return; raiseEvent(EVENT_Click, it); } void CIconView::renamed(QIconViewItem *it) { raiseEvent(EVENT_Rename, it); }