aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/skin/widgets/db
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/skin/widgets/db')
-rw-r--r--Src/Wasabi/api/skin/widgets/db/autofilterlist.cpp406
-rw-r--r--Src/Wasabi/api/skin/widgets/db/autofilterlist.h447
-rw-r--r--Src/Wasabi/api/skin/widgets/db/autoquerylist.cpp111
-rw-r--r--Src/Wasabi/api/skin/widgets/db/autoquerylist.h109
-rw-r--r--Src/Wasabi/api/skin/widgets/db/queryline.cpp32
-rw-r--r--Src/Wasabi/api/skin/widgets/db/queryline.h64
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiquerydrag.cpp103
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiquerydrag.h53
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiqueryline.cpp73
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiqueryline.h35
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiquerylist.cpp119
-rw-r--r--Src/Wasabi/api/skin/widgets/db/xuiquerylist.h72
12 files changed, 1624 insertions, 0 deletions
diff --git a/Src/Wasabi/api/skin/widgets/db/autofilterlist.cpp b/Src/Wasabi/api/skin/widgets/db/autofilterlist.cpp
new file mode 100644
index 00000000..513d8c44
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/autofilterlist.cpp
@@ -0,0 +1,406 @@
+#include <precomp.h>
+#include "autofilterlist.h"
+#include <api/db/subqueryserver.h>
+#include <api/script/objects/c_script/c_text.h>
+#include <api/script/objects/c_script/h_button.h>
+#include <api/wnd/popup.h>
+#include <bfc/file/filename.h>
+
+#define TIMER_SCANNERDEL 0x6891
+
+class ButtHooker : public H_Button {
+public:
+ ButtHooker(AutoFilterList *hangout, ScriptObject *butt) : afl(hangout), H_Button(butt) { }
+ void hook_onLeftClick() {
+ afl->doFieldPopup();
+ }
+
+private:
+ AutoFilterList *afl;
+};
+
+FilterListItem::FilterListItem(void *_data, int _datalen, int _datatype) {
+ data_len = _datalen;
+ data_type = _datatype;
+ data.setSize(data_len+1);
+ MEMCPY(data.getMemory(), _data, data_len);
+}
+
+AutoFilterList::AutoFilterList() {
+ showColumnsHeaders = FALSE;
+ local_scanner = NULL;
+ order = -1;
+ viscount = 0;
+ grab_playstrings = 0;
+ linked = 1;
+ hooker = NULL;
+ needrestart = 0;
+ querydirection = SetQuery::FORWARD;
+ last_populate_flag = -1;
+ setContent("wasabi.buttonbar.stack");
+ fn = NULL;
+ data_type = NULL;
+}
+
+AutoFilterList::~AutoFilterList() {
+ delete local_scanner;
+ delete hooker;
+}
+
+int AutoFilterList::onInit() {
+ AUTOFILTERLIST_PARENT::onInit();
+ //scannerserver_newScanner();
+
+ return 1;
+}
+
+void AutoFilterList::scannerserver_onNewScanner(SharedDbScannerI *scanner) {
+ AUTOFILTERLIST_DBPARENTSRV::scannerserver_onNewScanner(scanner);
+ delete local_scanner;
+ local_scanner = new dbScanner(scannerserver_getTable());
+ local_scanner->setQuery(sqs_getQuery());
+}
+
+void AutoFilterList::mqc_onNewMultiQuery(SubQueryServer *modifier, int flag) {
+ AUTOFILTERLIST_DBPARENTCLIENT::mqc_onNewMultiQuery(modifier);
+ if (!isInited()) return;
+ if (modifier == this && !needrestart) return;
+ if (local_scanner == NULL) return;
+ int id = sqs_getCooperativeId();
+ int need_reset = (modifier == NULL || needrestart);
+ if (!need_reset) switch (flag) {//glag!
+ default:
+ case SetQuery::FORWARD:
+ need_reset = (id >= modifier->sqs_getCooperativeId());
+ break;
+ case SetQuery::REVERSE:
+ need_reset = (id <= modifier->sqs_getCooperativeId());
+ break;
+ case SetQuery::GLOBAL:
+ need_reset = (id != modifier->sqs_getCooperativeId());
+ break;
+ }
+
+ if (need_reset) {
+ needrestart = 0;
+
+ last_populate_flag = flag;
+
+ int optimized = sqs_getMultiQueryServer() && sqs_getMultiQueryServer()->mqs_isQueryEmpty();
+
+ uniques.deleteAll();
+ deleteAllItems();
+
+ const char *allstr = getAllString();
+ FilterListItem *fli = new FilterListItem((void *)allstr, STRLEN(allstr)+1, MDT_STRINGZ);
+ insertItem(0, NULL, reinterpret_cast<LPARAM>(fli));
+ setSelected(0, 1);
+
+ SharedDbScannerI *shs = scannerserver_getScanner();
+ if (shs != NULL) {
+ dbSvcScanner *sc = shs->getScanner();
+ if (sc != NULL) sc->cancelQuery();
+ }
+ dbSvcScanner *lc= local_scanner->getScanner();
+ if (lc != NULL) lc->cancelQuery();
+
+ if (optimized) {
+ grab_playstrings = 0;
+ setRedraw(0);
+ dbScanner *unique_scanner = new dbScanner(sqs_getTable(), field);
+ while (!unique_scanner->eof()) {
+ char data[4096]="";
+ unique_scanner->getData("Value", data, 4095, MDT_STRINGZ);
+ data[4095]=0;
+ insertData(data, STRLEN(data)+1, MDT_STRINGZ);
+ unique_scanner->next();
+ }
+ setRedraw(1);
+ delete unique_scanner;
+ } else {
+ grab_playstrings = 1;
+ lc->cancelQuery();
+ }
+
+ return;
+ }
+}
+
+void AutoFilterList::mqc_onCompleteMultiQuery() {
+ grab_playstrings = 0;
+}
+
+void AutoFilterList::mqc_onAddPlaystring(const char *playstring, int nitems, int thispos) {
+ AUTOFILTERLIST_DBPARENTCLIENT::mqc_onAddPlaystring(playstring, nitems, thispos);
+ if (grab_playstrings)
+ filterEntry(playstring, local_scanner, field);
+}
+
+void AutoFilterList::setMetadataField(const char *_field) {
+ if (!field.isempty() && STRCASEEQL(field, _field)) return;
+ field = _field;
+ delColumnByPos(0);
+ addColumn(field, 100);
+ data_type = api->metadb_getMetaDataType(field);
+ sqs_setTable(api->metadb_getMetaDataTable(field));
+ if (isPostOnInit())
+ setLabelName();
+ sqs_setQuery("");
+ needrestart = 1;
+ scannerserver_newScanner();
+}
+
+int AutoFilterList::onResize() {
+ AUTOFILTERLIST_PARENT::onResize();
+ RECT r = clientRect();
+ ListColumn *c = enumListColumn(0);
+ if (!c) return 1;
+ c->setWidth(r.right-r.left-4);
+ recalcHeaders();
+
+ return 1;
+}
+
+void AutoFilterList::getClientRect(RECT *r) {
+ AUTOFILTERLIST_PARENT::getClientRect(r);
+ api_window *rw = getContentRootWnd();
+ if (rw) r->top += rw->getPreferences(SUGGESTED_H);
+// else r->top += 16;
+}
+
+void AutoFilterList::rootwndholder_getRect(RECT *r) {
+ getClientRect(r);
+ r->bottom = r->top;
+ api_window *rw = getContentRootWnd();
+ if (rw) r->top -= rw->getPreferences(SUGGESTED_H);
+// else r->top += 16;
+}
+
+void AutoFilterList::onNewContent() {
+ setLabelName();
+ // hook the clicks
+ delete hooker;
+ ScriptObject *mousetrap = findScriptObject("mousetrap");
+ hooker = new ButtHooker(this, mousetrap);
+}
+
+int AutoFilterList::ownerDraw(Canvas *canvas, int pos, RECT *r, LPARAM lParam, int isselected, int isfocused) {
+ COLORREF bgcolor = isfocused ? getFocusColor(lParam) : getSelBgColor(lParam);
+ COLORREF fgcolor = getTextColor(lParam);
+
+ RECT box;
+ canvas->getClipBox(&box);
+
+ if (!getBgBitmap()) {
+ RECT r2 = *r;
+ r2.left = box.left;
+ new RegionI reg(&r2);
+ canvas->selectClipRgn(&reg);
+ canvas->fillRect(r, getBgColor());
+ }
+
+ canvas->setTextColor(fgcolor);
+
+ if (isselected) {
+ RECT mr = *r;
+ canvas->fillRect(&mr, bgcolor);
+ }
+
+ if (isfocused)
+ canvas->drawRect(r, 0, getFocusColor(lParam));
+
+ canvas->pushTextSize(getFontSize());
+
+ int x = 1+r->left;
+ for (int i = 0; i < getNumColumns(); i++) {
+ RECT ir;
+ ir.left = x;
+ ir.right = x + getColumnWidth(i);
+ ir.top = r->top;
+ ir.bottom = r->bottom;
+ if (ir.right >= box.left && ir.bottom >= box.top && ir.left <= box.right && ir.top <= box.bottom) {
+ FilterListItem *fli = reinterpret_cast<FilterListItem *>(lParam);
+ api->metadb_renderData(canvas, ir, (void *)fli->getData(), fli->getDatatype(), 0);
+ }
+ x = ir.right;
+ }
+ canvas->popTextSize();
+ return 1;
+}
+
+void AutoFilterList::filterEntry(const char *playstring, dbScanner *scanner, const char *field) {
+ dbSvcScanner *sp = scanner->getScanner();
+ if (sp != NULL) sp->push();
+ scanner->setIndexName(MT_PLAYSTRING);
+ scanner->setIndexValue(playstring);
+ scanner->first();
+
+ if (scanner->eof()) return;
+
+ char data[4096]="";
+ scanner->getData((char *)field, data, 4095, data_type);
+ data[4095]=0;
+
+ sp->pop();
+
+ switch (data_type) {
+ case MDT_INT:
+ case MDT_TIME:
+ case MDT_BOOLEAN:
+ case MDT_TIMESTAMP:
+ filterInt(*(int *)data);
+ break;
+ case MDT_STRINGZ:
+ filterString((const char *)data);
+ break;
+ }
+}
+
+void AutoFilterList::filterInt(int data) {
+ int pos=0;
+ if (uniques.findItem((const char *)&data, &pos)) return;
+ insertData(&data, 4, data_type);
+}
+
+void AutoFilterList::insertData(void *data, int len, int type) {
+ int pos=0;
+ FilterListItem *fli = new FilterListItem(data, len, type);
+ uniques.addItem(fli);
+ pos = uniques.searchItem(fli);
+ insertItem(pos+1/*+1 for item ALL at the top*/, NULL, reinterpret_cast<LPARAM>(fli));
+}
+
+void AutoFilterList::filterString(const char *data) {
+ if (!data || !*data) return;
+ int pos=0;
+ if (uniques.findItem(data, &pos)) return;
+ insertData((void *)data, STRLEN(data)+1, data_type);
+}
+
+void AutoFilterList::onLeftClick(int itemnum) {
+
+ if (itemnum == 0 && last_populate_flag != lastflag) {
+ needrestart = 1;
+ }
+ String query;
+ if (itemnum > 0) {
+ for (int i=0;i<getNumItems();i++) {
+ if (getItemSelected(i)) {
+ if (!query.isempty())
+ query += " || ";
+ query += field;
+ query += " == ";
+ FilterListItem *fli = reinterpret_cast<FilterListItem *>(getItemData(i));
+ switch (fli->getDatatype()) {
+ case MDT_INT:
+ case MDT_TIME:
+ case MDT_BOOLEAN:
+ case MDT_TIMESTAMP:
+ query += StringPrintf("%d", *(int *)fli->getData());
+ break;
+ case MDT_STRINGZ:
+ query += "\"";
+ query += fli->getData();
+ query += "\"";
+ break;
+ }
+ }
+ }
+ }
+ sqs_setQuery(query, querydirection);
+ if (local_scanner != NULL) local_scanner->setQuery(query);
+}
+
+void AutoFilterList::onDoubleClick(int itemnum) {
+ int sav = querydirection;
+ querydirection = SetQuery::GLOBAL;
+ onLeftClick(itemnum);
+ querydirection = sav;
+}
+
+void AutoFilterList::sqs_onAttachServer(MultiQueryServer *s) {
+ s->mqs_registerClient(this);
+}
+
+void AutoFilterList::sqs_onDetachServer(MultiQueryServer *s) {
+ s->mqs_unregisterClient(this);
+}
+
+void AutoFilterList::sqs_reset() {
+ postDeferredCallback(7873, 3245);
+}
+
+int AutoFilterList::onDeferredCallback(intptr_t p1, intptr_t p2) {
+ if (p1 == 7873 && p2 == 3245) {
+ deselectAll();
+ setItemFocused(0);
+ setSelected(0, TRUE);
+ needrestart=1; last_populate_flag = -1;
+ onLeftClick(0);
+ ensureItemVisible(0);
+ return 1;
+ }
+ return AUTOFILTERLIST_PARENT::onDeferredCallback(p1, p2);
+}
+
+void AutoFilterList::setLabelName() {
+ ScriptObject *tx = findScriptObject("buttonbar.text");
+ if (tx == NULL) return;
+ C_Text(tx).setText(field);
+}
+
+void AutoFilterList::setQueryDirection(int glag) {
+ querydirection = glag;
+}
+
+void AutoFilterList::doFieldPopup() {
+ PopupMenu popup;
+ dbSvcScanner *scanner = api->metadb_newScanner(sqs_getTable());
+ if (scanner == NULL) return;
+ int n = scanner->getNumCols();
+ PtrListQuickSorted<String, StringComparator> fields;
+ for (int i = 0; i < n; i++) {
+ dbSvcColInfo *info = scanner->enumCol(i);
+ if (!info->uniques_indexed) continue;
+ fields.addItem(new String(info->name));
+ }
+ fields.sort();
+ foreach(fields)
+ const char *name = fields.getfor()->getValue();
+ int checked = STRCASEEQLSAFE(name, field);
+ popup.addCommand(name, foreach_index, checked);
+ endfor
+ RECT cr = clientRect();
+ clientToScreen((int *)&cr.left, (int *)&cr.top);
+ int r = popup.popAtXY(cr.left, cr.top);
+ if (r >= 0) {
+ const char *col = fields.enumItem(r)->getValue();
+ dbSvcColInfo *info = scanner->getColByName(col);
+ setMetadataField(info->name);
+ }
+ fields.deleteAll();
+ api->metadb_deleteScanner(scanner);
+}
+
+void AutoFilterList::onVScrollToggle(BOOL set) {
+ AUTOFILTERLIST_PARENT::onVScrollToggle(set);
+ if (getContentRootWnd() && isPostOnInit())
+ onResize();
+}
+
+int AutoFilterList::onBeginDrag(int iItem) {
+ String query;
+ FilterListItem *fli = reinterpret_cast<FilterListItem *>(getItemData(iItem));
+ if (fli == NULL) return 0; // BU added in response to talkback data we'll see if it helps
+ String val = (fli->getDatatype() == MDT_STRINGZ) ? fli->getData() : StringPrintf(*(int *)fli->getData()).getValue();
+ fn = new FilenameI(StringPrintf("query://%s;\"%s\" == \"%s\"", StringPrintf(scannerserver_getTable()).getValue(), field.getValue(), val.getValue()));
+ addDragItem(Filename::dragitem_getDatatype(), static_cast<Filename*>(fn));
+ handleDrag();
+ return 1;
+}
+
+int AutoFilterList::dragComplete(int success) {
+ delete fn; fn = NULL;
+ return 1;
+}
+
diff --git a/Src/Wasabi/api/skin/widgets/db/autofilterlist.h b/Src/Wasabi/api/skin/widgets/db/autofilterlist.h
new file mode 100644
index 00000000..df998465
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/autofilterlist.h
@@ -0,0 +1,447 @@
+#ifndef __AUTOFILTERLIST_H
+#define __AUTOFILTERLIST_H
+
+#include "../std.h"
+#include "listwnd.h"
+#include "../db/scanner.h"
+#include "../timeslicer.h"
+#include "../db/subqueryserver.h"
+#include "../db/multiqueryclient.h"
+#include "autoquerylist.h"
+
+/**
+ A filter list item is a data item of any type or
+ size to put on a FilterList. The type and size are accessible
+ for memory management purposes.
+
+ @short Items for FilterLists
+ @author Nullsoft
+ @ver 1.0
+ @see FilterListItemSort, MultiQueryServer
+*/
+class FilterListItem {
+ public:
+
+ /**
+ Allocates memory for copying a data
+ object, and then copies the object into newly allocated memory.
+
+ @see MemBlock
+ @see VoidMemblock
+ @param _data Pointer to a data object
+ @param _datalen Length of data object
+ @param _datatype Type of data object
+ */
+ FilterListItem(void *_data, int _datalen, int _datatype);
+
+ /**
+ Does nothing.
+ */
+ virtual ~FilterListItem() { }
+
+ /**
+ Get the data associated with the filter
+ list item.
+
+ @see getDatatype()
+ @see getDataLen()
+ @ret A pointer to the data.
+ */
+ const char *getData() { return data.getMemory(); }
+
+ /**
+ Get the type of the data associated with the
+ filter list item.
+
+ @see getData()
+ @see getDataLen()
+ @see metatags.h
+ @ret Data type of item.
+ */
+ int getDatatype() { return data_type; }
+
+ /**
+ Get the length of the data (in bytes).
+
+ @see getDatatype()
+ @see getData()
+ @ret Length of data (in bytes).
+ */
+ int getDataLen() { return data_len; }
+
+ private:
+
+ MemBlock<char> data;
+ int data_type;
+ int data_len;
+};
+
+/**
+ Provides methods for sorting a FilterList.
+
+ @short FilterList sorting.
+ @author Nullsoft
+ @ver 1.0
+ @see FilterListItem
+*/
+class FilterListItemSort {
+ public:
+ /**
+ Determines the data types of two objects and
+ calls an appropriate comparison function to compare them.
+
+ @assert The two objects to be compared have the same data type.
+ @see compareAttrib()
+ @ret -1, _p1 < _p2; 0, _p1 = _p2; 1, _p1 > _p2
+ @param _p1 Object to compare
+ @param _p2 Object to compare
+ */
+ static int compareItem(void *_p1, void *_p2) {
+ FilterListItem *p1 = ((FilterListItem *)_p1);
+ FilterListItem *p2 = ((FilterListItem *)_p2);
+ ASSERT(p1->getDatatype() == p2->getDatatype());
+ switch (p1->getDatatype()) {
+ case MDT_INT:
+ case MDT_TIME:
+ case MDT_BOOLEAN:
+ case MDT_TIMESTAMP: {
+ int a = *(int *)p1->getData();
+ int b = *(int *)p2->getData();
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0; }
+ case MDT_STRINGZ:
+ return STRICMP(p1->getData(), p2->getData());
+ }
+ return 0;
+ }
+
+ /**
+ Compares the value of an item to an attribute string,
+ or to the value of the attribute string cast to an
+ appropriate data type.
+
+ @see compareItem()
+ @ret -1, _p1 < _p2; 0, _p1 = _p2; 1, _p1 > _p2
+ @param attrib
+ @param _item
+ */
+ static int compareAttrib(const wchar_t *attrib, void *_item) {
+ FilterListItem *item = ((FilterListItem *)_item);
+ switch (item->getDatatype()) {
+ case MDT_INT:
+ case MDT_TIME:
+ case MDT_BOOLEAN:
+ case MDT_TIMESTAMP: {
+ int a = *(int *)attrib;
+ int b = *(int *)item->getData();
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0; }
+ case MDT_STRINGZ:
+ return STRICMP(attrib, item->getData());
+ }
+ return 0;
+ }
+};
+
+class ButtHooker;
+class FilenameI;
+
+#define AUTOFILTERLIST_PARENT ListWnd
+#define AUTOFILTERLIST_DBPARENTSRV SubQueryServerI
+#define AUTOFILTERLIST_DBPARENTCLIENT MultiQueryClientI
+
+/**
+ A list of items to filter on.
+
+ @short A list of items to filter on.
+ @author Nullsoft
+ @ver 1.0
+ @see FilterListItemSort
+ @see FilterListItem
+*/
+class AutoFilterList : public AUTOFILTERLIST_PARENT,
+ public AUTOFILTERLIST_DBPARENTSRV,
+ public AUTOFILTERLIST_DBPARENTCLIENT {
+ public:
+
+ /**
+ Creates an empty filter list with a NULL local scanner.
+
+ @see ~AutoFilterList()
+ */
+ AutoFilterList();
+
+ /**
+ Deletes the local scanner.
+
+ @see AutoFilterList()
+ */
+ virtual ~AutoFilterList();
+
+ /**
+ Sets the field name and sets the scanner to NULL.
+
+ @param field The name of the field.
+ */
+ void setMetadataField(const char *field);
+
+ /**
+ Creates and populates the list.
+
+ @ret 1
+ */
+ virtual int onInit();
+
+ /**
+ Prepares a window for repainting in a new size.
+
+ @ret 1
+ */
+ virtual int onResize();
+
+ virtual void getClientRect(RECT *);
+ virtual void rootwndholder_getRect(RECT *r);
+ virtual void onNewContent();
+
+ /**
+ Displays a window in a specified position and state.
+
+ @ret 1
+ @param canvas
+ @param pos
+ @param r
+ @param lParam
+ @param isselected
+ @param isfocused
+ */
+ virtual int ownerDraw(Canvas *canvas, int pos, RECT *r, LPARAM lParam, int isselected, int isfocused);
+
+ /**
+ Event is triggered when the user clicks (with the left mouse
+ button) on an item in the auto filter list.
+
+ @param itemnum The number of the item that was clicked.
+ */
+ virtual void onLeftClick(int itemnum);
+
+ /**
+ Event is triggered when the user double-clicks (with the left mouse
+ button) on an item in the auto filter list.
+
+ @param itemnum The number of the item that was double-clicked.
+ */
+ virtual void onDoubleClick(int itemnum); // double-click on an item
+
+ /**
+ Gets the dependency pointer.
+
+ @ret The dependency pointer.
+ */
+ virtual api_dependent *timeslicer_getDependencyPtr() { return rootwnd_getDependencyPtr(); }
+
+ /**
+ Returns the proper query string for "all items"
+ present in the list.
+
+ @ret Query string for "all items".
+ */
+ virtual const char *getAllString() { return "All"; }
+
+
+ /**
+ Deletes the current scanner and sets up a new one.
+
+ @param A shared database scanner
+ */
+ virtual void scannerserver_onNewScanner(SharedDbScannerI *scanner);
+
+ /**
+ Makes the necessary preparations for running a new query.
+
+ @see SetQuery
+ @see MultiQueryServer, SubQueryServer
+ @param modifier refers to a SubQueryServer, which implements a simple filter.
+ @param flag The type of query that will be performed.
+ */
+ virtual void mqc_onNewMultiQuery(SubQueryServer *modifier, int flag);
+
+ /**
+ Gets the dependency pointer.
+
+ @see api_dependent
+ @ret Dependency Dependency pointer
+ */
+ virtual api_dependent *mqc_getDependencyPtr() { return rootwnd_getDependencyPtr(); }
+
+ /**
+ Sets the order of the result list.
+ <b>Not currently implemented!</b>
+
+ @param order order desired for the result list.
+ */
+ void setOrder(int n) { order = n; }
+
+ /**
+ Gets the order number.
+
+ @see setOrder()
+ @ret Order number if linked, otherwise -1
+ @param None
+ */
+ virtual int sqs_getCooperativeId() { return linked ? order : -1; }
+
+ /**
+ Event is triggered when a multi query has completed.
+ Has no external effect.
+ */
+ virtual void mqc_onCompleteMultiQuery();
+
+ /**
+ Tests whether to enter a playstring in a filter entry, and does it if
+ necessary.
+
+ @param playstring The playstring being added.
+ @param nitems HELP
+ @param thispos HELP
+ */
+ virtual void mqc_onAddPlaystring(const char *playstring, int nitems, int thispos);
+
+
+ /**
+ Registers a client with a query server.
+
+ @see sqs_onDetachServer()
+ @param s The server we will register to.
+ */
+ virtual void sqs_onAttachServer(MultiQueryServer *s);
+
+ /**
+ Unregisters a client with a query server.
+
+ @see sqs_onAttachServer()
+ @param s The server we will unregister from.
+ */
+ virtual void sqs_onDetachServer(MultiQueryServer *s);
+
+ /**
+ Resets the query.
+ */
+ virtual void sqs_reset();
+
+ /**
+ Generic deferred callback interface.
+ */
+ virtual int onDeferredCallback(intptr_t p1, intptr_t p2);
+
+ /**
+ Sets the linking status according to the value v.
+
+ @param v linking status to set
+ */
+ virtual void setLinked(int v) { linked = v; }
+
+ /**
+ Set the direction of the query.
+
+ @see SetQuery
+ @param glag The direction of the query.
+ */
+ void setQueryDirection(int glag);
+
+ /**
+ HELP
+ */
+ void doFieldPopup();
+
+ /**
+ HELP
+ */
+ virtual void onVScrollToggle(BOOL set);
+
+ /**
+ HELP
+ */
+ virtual int wantRenderBaseTexture() { return 1; }
+
+ /**
+ Event is triggered when an item is
+ being dragged.
+
+ @param iItem The item being dragged.
+ @ret 0, Drag not handled; 1, Drag handled;
+ */
+ virtual int onBeginDrag(int iItem);
+
+ /**
+ Gets called when the API thinks the drag and drop
+ was successful.
+
+ @param success Drag and Drop succeeded? (According to API).
+ @ret 0, Drag and Drop not sucessful; 1, Drop and Drop completed successfully;
+ */
+ virtual int dragComplete(int success);
+
+ private:
+ /**
+ HELP
+ */
+ void populate();
+
+ /**
+ Finds a specific entry in the database.
+
+ @param playstring The playstring for the item.
+ @param scanner The db scanner to use.
+ @param field The field to be read.
+ */
+ void filterEntry(const char *playstring, dbScanner *scanner, const char *field);
+
+ /**
+ Filters and formats integer type data
+ and inserts it into the list to be displayed.
+ */
+ void filterInt(int data);
+
+ /**
+ Filters and formats string type data
+ and inserts it into the list to be displayed.
+ */
+ void filterString(const char *data);
+
+ /**
+ Inserts data into the list so that it may be
+ displayed.
+
+ @see metatags.h
+ @param data The data to insert.
+ @param len The length of the data to insert.
+ @param type The type of the data to insert.
+ */
+ void insertData(void *data, int len, int type);
+
+ /**
+ Sets the filter label to the meta data field we are
+ currently sorting on.
+
+ @see filterEntry()
+ */
+ void setLabelName();
+
+ String field;
+ dbScanner *local_scanner;
+ PtrListInsertSorted<FilterListItem, FilterListItemSort> uniques;
+ int data_type;
+ int order;
+ int grab_playstrings;
+ int viscount;
+ int linked;
+ int needrestart;
+ int querydirection;
+ int last_populate_flag;
+ ButtHooker *hooker;
+ FilenameI *fn;
+};
+
+#endif
diff --git a/Src/Wasabi/api/skin/widgets/db/autoquerylist.cpp b/Src/Wasabi/api/skin/widgets/db/autoquerylist.cpp
new file mode 100644
index 00000000..5513cb34
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/autoquerylist.cpp
@@ -0,0 +1,111 @@
+#include <precomp.h>
+#include "autoquerylist.h"
+#include <api/db/subqueryserver.h>
+#include <api/db/multiqueryclient.h>
+#include <api/db/sharedscanner.h>
+#include <bfc/string/playstring.h>
+#include <api/db/metatags.h>
+#include <api/wnd/fakedrag.h>
+#include <bfc/util/profiler.h>
+#include <bfc/file/filename.h>
+#include <api/api.h>
+#include <api/service/svcs/svc_droptarget.h>
+#include <api/service/svc_enum.h>
+
+#include "../../pledit/svc_pldir.h"
+#include "../../pledit/playlist.h"
+#include "../../pledit/editor.h"
+
+#define TIMER_SCANNERDEL 0x6879
+#define DC_REFRESH 0x6880
+
+AutoQueryList::AutoQueryList() :
+ playlist(NULL)
+{
+ lastpc = -1;
+ last_status_update = 0;
+ pldir = NULL;
+ nFound = 0;
+}
+
+AutoQueryList::~AutoQueryList() {
+ getGuiObject()->guiobject_removeAppCmds(this);
+ SvcEnum::release(pldir);
+}
+
+int AutoQueryList::onInit() {
+ AUTOQUERYLIST_PARENT::onInit();
+
+ pldir = SvcEnumByGuid<svc_plDir>();
+ if (pldir != NULL) {
+ PlaylistHandle hand = pldir->insertPlaylist(NULL, "Media library query results", NULL, TRUE);
+ pldir->setAutoSave(hand, FALSE);
+ playlist = pldir->getPlaylist(hand);
+ playlist->lock(TRUE);
+ }
+
+ appcmds_addCmd("Reset", 0, AppCmds::SIDE_RIGHT);
+ getGuiObject()->guiobject_addAppCmds(this);
+
+ postDeferredCallback(DC_REFRESH, 0);
+
+ return 1;
+}
+
+int AutoQueryList::onDeferredCallback(intptr_t p1, intptr_t p2) {
+ if (p1 == DC_REFRESH) {
+ mqs_refresh();
+ return 0;
+ }
+ return AUTOQUERYLIST_PARENT::onDeferredCallback(p1, p2);
+}
+
+void AutoQueryList::mqs_onAddPlaystring(const char *playstring, int nitems, int thispos) {
+ nfound++;
+ stdtimevalms now = Std::getTimeStampMS();
+// if (n > lastpc) {
+ if (now - last_status_update > 0.100) {
+ int n = (int)(thispos / (float)nitems * 100.0f);
+ getGuiObject()->guiobject_setCompleted(n);
+ getGuiObject()->guiobject_setStatusText(StringPrintf("%d%c, %d item%s found", n, '%', nfound, (nfound > 1) ? "s" : ""), TRUE);
+// lastpc = n;
+// }
+ last_status_update = now;
+ }
+ if (playlist != NULL)
+ playlist->addPlaylistItem(playstring, Playlist::APPEND, FALSE);
+}
+
+void AutoQueryList::mqs_onCompleteMultiQuery() {
+ getGuiObject()->guiobject_setStatusText(StringPrintf("100%c, %d item%s found", '%', nfound, (nfound > 1) ? "s" : ""), TRUE);
+ lastpc = -1;
+ getGuiObject()->guiobject_popCompleted();
+}
+
+void AutoQueryList::mqs_onNewMultiQuery() {
+ nfound = 0;
+ getGuiObject()->guiobject_setStatusText("0%", TRUE);
+ getGuiObject()->guiobject_pushCompleted();
+ if (playlist != NULL) {
+ playlist->deleteAll();
+
+ GuiObject *ed = getGuiObject()->guiobject_findObjectByInterface(Editor::getInterfaceGuid());
+ if (ed != NULL) {
+ Editor *e = static_cast<Editor*>(ed->guiobject_getRootWnd()->getInterface(Editor::getInterfaceGuid()));
+ e->setPlaylistByHandle(playlist->getHandle());
+ }
+ }
+}
+
+void AutoQueryList::appcmds_onCommand(int id, const RECT *buttonRect, int which_btn) {
+ switch (id) {
+ case 0:
+ resetSubQueries();
+ break;
+ }
+}
+
+void AutoQueryList::onSetVisible(int v) {
+ AUTOQUERYLIST_PARENT::onSetVisible(v);
+ if (!v) mqs_abort();
+}
diff --git a/Src/Wasabi/api/skin/widgets/db/autoquerylist.h b/Src/Wasabi/api/skin/widgets/db/autoquerylist.h
new file mode 100644
index 00000000..2ed7cd55
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/autoquerylist.h
@@ -0,0 +1,109 @@
+#ifndef __AUTOQUERYLIST_H
+#define __AUTOQUERYLIST_H
+
+#include "itemlistwnd.h"
+#include "../db/multiqueryserver.h"
+#include "../ptrlist.h"
+#include "../string.h"
+#include "../timeslicer.h"
+#include "../appcmds.h"
+#include "../../pledit/plhand.h"
+#include "../nakedobject.h"
+
+class svc_plDir;
+class Playlist;
+
+#define AUTOQUERYLIST_PARENT NakedObject
+#define AUTOQUERYLIST_DBPARENTSRV MultiQueryServerI
+
+/**
+ Automates the display of the result set of
+ a query.
+
+ Simply create an AutoQueryList instance,
+ set it's query with setQuery().
+
+ Can send results to the playlist directory
+ for automatic playlist creation based on
+ the result of the query.
+
+ @short Automated query result display window.
+ @author Nullsoft
+ @ver 1.0
+ @see AutoFilterList
+*/
+class AutoQueryList : public AUTOQUERYLIST_PARENT,
+ public AUTOQUERYLIST_DBPARENTSRV, AppCmdsI {
+
+ public:
+ /**
+ Initializes member data.
+ */
+ AutoQueryList();
+
+ /**
+ Releases playlist directory service and removes
+ the AppCmd button.
+ */
+ virtual ~AutoQueryList();
+
+ /**
+ Initializes the auto query list.
+
+ ret 1
+ */
+ virtual int onInit();
+
+ /**
+ Event is triggered when a playstring is added to the result list.
+
+ Updates the progress bar at the bottom of the window (from 0 to 100%).
+
+ @param playstring The playstring to being added to the result list.
+ @param nitems The number of items (total) in the result list.
+ @param thispos The current position in the list of items.
+ */
+ virtual void mqs_onAddPlaystring(const char *playstring, int nitems, int thispos);
+
+ /**
+ Event is triggered when a new query is set.
+
+ Updates the progress bar to 0%, resets the playlist associated
+ with this auto query list and resets the number of items found
+ for the query to zero.
+ */
+ virtual void mqs_onNewMultiQuery();
+
+ /**
+ Event is triggered when a query completes.
+
+ Updates the progress bar to 100% and resets the last
+ known progress count.
+ */
+ virtual void mqs_onCompleteMultiQuery();
+ virtual int onDeferredCallback(intptr_t p1, intptr_t p2);
+
+protected:
+ /**
+ Event is triggered when an AppCmd button (which belongs to this
+ auto query list) is pushed.
+
+ Only one command is handled by the auto query list which causes the query
+ to be reset. The id of the command is 0.
+
+ @param id The id of the command associated with the button that was pressed.
+ @param rect The RECT of the button that was pushed.
+ */
+ virtual void appcmds_onCommand(int id, const RECT *buttonRect, int which_btn);
+ virtual void onSetVisible(int v);
+
+private:
+
+ int lastpc;
+ int nfound;
+ Playlist *playlist;
+ svc_plDir *pldir;
+ stdtimevalms last_status_update;
+};
+
+#endif
diff --git a/Src/Wasabi/api/skin/widgets/db/queryline.cpp b/Src/Wasabi/api/skin/widgets/db/queryline.cpp
new file mode 100644
index 00000000..4f844508
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/queryline.cpp
@@ -0,0 +1,32 @@
+#include <precomp.h>
+
+#include "queryline.h"
+
+#include <api/api.h>
+#include <api/db/metatags.h>
+#include <bfc/string/string.h>
+#include <bfc/parse/pathparse.h>
+
+QueryLine::QueryLine(const char *query) : autoquery(FALSE), querytext(query), autofield(MT_NAME) {
+}
+
+void QueryLine::setQuery(const char *query) {
+ querytext = query;
+ String sp = querytext;
+ if (autoquery && !querytext.isempty()) {
+ sp = "";
+ PathParser pp(querytext, " ");
+ if (pp.getNumStrings() <= 0) return;
+ for (int i = 0; i < pp.getNumStrings(); i++) {
+ if (i != 0) sp += " and ";
+ sp += StringPrintf("(\"%s\" has \"%s\")", autofield.getValue(), pp.enumString(i));
+ }
+ }
+ sqs_setQuery(sp);
+}
+
+int QueryLine::setAuto(int bv) {
+ autoquery = !!bv;
+ setQuery(querytext);
+ return 1;
+}
diff --git a/Src/Wasabi/api/skin/widgets/db/queryline.h b/Src/Wasabi/api/skin/widgets/db/queryline.h
new file mode 100644
index 00000000..4743e731
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/queryline.h
@@ -0,0 +1,64 @@
+#ifndef _QUERYLINE_H
+#define _QUERYLINE_H
+
+#include <api/skin/nakedobject.h>
+#include <api/db/subqueryserver.h>
+
+#define QUERYLINE_PARENT NakedObject
+
+/**
+ Class
+
+ @short
+ @author Nullsoft
+ @ver 1.0
+ @see
+*/
+class QueryLine : public QUERYLINE_PARENT, public SubQueryServerI {
+public:
+
+ /**
+ Method
+
+ @see
+ @ret
+ @param
+ */
+ QueryLine(const char *query=NULL);
+
+ /**
+ Method
+
+ @see
+ @ret
+ @param
+ */
+ virtual ~QueryLine() { }
+
+
+ /**
+ Method
+
+ @see
+ @ret
+ @param
+ */
+ virtual void setQuery(const char *query);
+
+ /**
+ Method
+
+ @see
+ @ret
+ @param
+ */
+ int setAuto(int bv);
+
+protected:
+ int autoquery;
+
+private:
+ String querytext, autofield;
+};
+
+#endif
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.cpp b/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.cpp
new file mode 100644
index 00000000..c1981774
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.cpp
@@ -0,0 +1,103 @@
+#include <precomp.h>
+#include "xuiquerydrag.h"
+#include <tataki/canvas/ifc_canvas.h>
+#include <api/db/multiqueryserver.h>
+#include <bfc/file/filename.h>
+
+char QueryDragXuiObjectStr[] = "QueryDrag"; // This is the xml tag
+char QueryDragXuiSvcName[] = "QueryDrag xui object"; // and this is the name of the service
+
+XMLParamPair QueryDrag::params[] = {
+ {QUERYDRAG_SETIMAGE, "image"},
+ {QUERYDRAG_SETSOURCE, "source"},
+ };
+QueryDrag::QueryDrag() {
+ setVirtual(0); // fucko
+ myxuihandle = newXuiHandle();
+
+
+ int numParams = sizeof(params) / sizeof(params[0]);
+ hintNumberOfParams(numParams);
+ for (int i = 0;i < numParams;i++)
+ addParam(myxuihandle, params[i], XUI_ATTRIBUTE_IMPLIED);
+ fn = NULL;
+}
+
+QueryDrag::~QueryDrag() {
+}
+
+int QueryDrag::setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value) {
+ if (xuihandle != myxuihandle)
+ return QUERYDRAG_PARENT::setXuiParam(xuihandle, xmlattributeid, xmlattributename, value);
+
+ switch (xmlattributeid) {
+ case QUERYDRAG_SETIMAGE:
+ setImage(value);
+ break;
+ case QUERYDRAG_SETSOURCE:
+ setSource(value);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+int QueryDrag::onPaint(Canvas *canvas) {
+ QUERYDRAG_PARENT::onPaint(canvas);
+
+ RECT r;
+ getClientRect(&r);
+
+ RenderBaseTexture(canvas, r, 255);
+
+ if (image.getBitmap())
+ image.getBitmap()->stretchToRectAlpha(canvas, &r, getPaintingAlpha());
+
+ return 1;
+}
+
+void QueryDrag::setImage(const char *elementname) {
+ image = elementname;
+ if (isInited()) invalidate();
+}
+
+void QueryDrag::setSource(const char *elementname) {
+ source = elementname;
+}
+
+int QueryDrag::getPreferences(int what) {
+ switch (what) {
+ case SUGGESTED_W:
+ if (image.getBitmap()) return image.getBitmap()->getWidth();
+ case SUGGESTED_H:
+ if (image.getBitmap()) return image.getBitmap()->getHeight();
+ }
+ return QUERYDRAG_PARENT::getPreferences(what);
+}
+
+int QueryDrag::onMouseMove(int x, int y) {
+ QUERYDRAG_PARENT::onMouseMove(x,y);
+ if (isInClick())
+ onBeginDrag();
+ return 1;
+}
+
+void QueryDrag::onBeginDrag() {
+ api_window *mqsw = NULL;
+ if (source.isempty()) mqsw = findWindowByInterface(multiQueryServerGuid);
+ else mqsw = findWindow(source);
+ if (!mqsw) return;
+ MultiQueryServer *mqs = static_cast<MultiQueryServer *>(mqsw->getInterface(multiQueryServerGuid));
+
+ // multiquery is now available in mqs->mqs_getMultiQuery(); using format "table guid;query;table guid;query;etc..."
+ fn = new FilenameI(StringPrintf("query://%s.nsq", mqs->mqs_getMultiQuery()));
+ addDragItem(Filename::dragitem_getDatatype(), static_cast<Filename*>(fn));
+ handleDrag();
+}
+
+int QueryDrag::dragComplete(int success) {
+ ASSERT(fn != NULL);
+ delete fn; fn = NULL;
+ return 1;
+}
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.h b/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.h
new file mode 100644
index 00000000..6dad07ae
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiquerydrag.h
@@ -0,0 +1,53 @@
+#ifndef __QUERYDRAG_H
+#define __QUERYDRAG_H
+
+#include <api/wnd/wndclass/guiobjwnd.h>
+#include <tataki/bitmap/autobitmap.h>
+
+class FilenameI;
+
+#define QUERYDRAG_PARENT GuiObjectWnd
+
+// -----------------------------------------------------------------------
+// Your wnd object class
+
+class QueryDrag : public QUERYDRAG_PARENT {
+
+ public:
+
+ QueryDrag();
+ virtual ~QueryDrag();
+
+ virtual int onPaint(Canvas *c);
+ virtual int getPreferences(int what);
+ virtual int onMouseMove(int x, int y);
+
+ virtual int setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value);
+
+ void setImage(const char *elementname);
+ void setSource(const char *elementname);
+ void onBeginDrag();
+ virtual int dragComplete(int success);
+
+ private:
+
+ AutoSkinBitmap image;
+ String source;
+
+ FilenameI *fn;
+
+ enum {
+ QUERYDRAG_SETIMAGE = 0,
+ QUERYDRAG_SETSOURCE,
+ };
+ static XMLParamPair params[];
+ int myxuihandle;
+};
+
+
+// -----------------------------------------------------------------------
+extern char QueryDragXuiObjectStr[];
+extern char QueryDragXuiSvcName[];
+class QueryDragXuiSvc : public XuiObjectSvc<QueryDrag, QueryDragXuiObjectStr, QueryDragXuiSvcName> {};
+
+#endif
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiqueryline.cpp b/Src/Wasabi/api/skin/widgets/db/xuiqueryline.cpp
new file mode 100644
index 00000000..2de3c918
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiqueryline.cpp
@@ -0,0 +1,73 @@
+#include <precomp.h>
+
+#include "xuiqueryline.h"
+#include <api/skin/widgets/db/xuiquerylist.h>
+
+#define CB_SETQUERYLIST 0x1978
+
+char QueryLineXuiObjectStr[] = "QueryLine"; // This is the xml tag
+char QueryLineXuiSvcName[] = "QueryLine xui object";
+
+ScriptQueryLine::ScriptQueryLine() {
+ myxuihandle = newXuiHandle();
+ addParam(myxuihandle, "querylist", QUERYLINE_SETQUERYLIST, XUI_ATTRIBUTE_IMPLIED);
+ addParam(myxuihandle, "query", QUERYLINE_SETQUERY, XUI_ATTRIBUTE_IMPLIED);
+ addParam(myxuihandle, "auto", QUERYLINE_SETAUTO, XUI_ATTRIBUTE_IMPLIED);
+}
+
+ScriptQueryLine::~ScriptQueryLine() { }
+
+/*int ScriptQueryLine::onInit() {
+ SCRIPTQUERYLINE_PARENT::onInit();
+ if (!querylist_id.isempty())
+ postDeferredCallback(CB_SETQUERYLIST, 0, 500);
+ return 1;
+}*/
+
+int ScriptQueryLine::setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value) {
+ if (xuihandle != myxuihandle)
+ return SCRIPTQUERYLINE_PARENT::setXuiParam(xuihandle, xmlattributeid, xmlattributename, value);
+
+ switch (xmlattributeid) {
+ case QUERYLINE_SETQUERYLIST:
+ setXuiQueryList(value);
+ break;
+ case QUERYLINE_SETQUERY:
+ ql_setQuery(value);
+ break;
+ case QUERYLINE_SETAUTO:
+ setAuto(WTOI(value));
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void ScriptQueryLine::ql_setQuery(const char *q) {
+ ensureConnected();
+ setQuery(q);
+}
+
+void ScriptQueryLine::ensureConnected() {
+ api_window *o = findWindow(querylist_id);
+ if (!o) return;
+ ScriptQueryList *querylist = static_cast<ScriptQueryList *>(o->getInterface(queryListGuid));
+ if (!querylist) return;
+ sqs_setMultiQueryServer(querylist);
+}
+
+void ScriptQueryLine::setXuiQueryList(const char *v) {
+ querylist_id = v;
+}
+
+/*int ScriptQueryLine::onDeferredCallback(intptr_t p1, intptr_t p2) {
+ switch (p1) {
+ case CB_SETQUERYLIST:
+ break;
+ default:
+ return SCRIPTQUERYLINE_PARENT::onDeferredCallback(p1, p2);
+ }
+ return 1;
+}
+*/ \ No newline at end of file
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiqueryline.h b/Src/Wasabi/api/skin/widgets/db/xuiqueryline.h
new file mode 100644
index 00000000..a65554e6
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiqueryline.h
@@ -0,0 +1,35 @@
+#ifndef _XUIQUERYLINE_H
+#define _XUIQUERYLINE_H
+
+#include <api/skin/widgets/db/queryline.h>
+
+#define SCRIPTQUERYLINE_PARENT QueryLine
+class ScriptQueryLine : public SCRIPTQUERYLINE_PARENT {
+public:
+ ScriptQueryLine();
+ virtual ~ScriptQueryLine();
+
+ //virtual int onInit();
+
+ virtual int setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value);
+ void setXuiQueryList(const char *v);
+
+ //virtual int onDeferredCallback(intptr_t p1, intptr_t p2);
+
+private:
+ enum {
+ QUERYLINE_SETQUERYLIST=1,
+ QUERYLINE_SETQUERY,
+ QUERYLINE_SETAUTO,
+ };
+ void ql_setQuery(const char *);
+ void ensureConnected();
+ int myxuihandle;
+ String querylist_id;
+};
+
+extern char QueryLineXuiObjectStr[];
+extern char QueryLineXuiSvcName[];
+class QueryLineXuiSvc : public XuiObjectSvc<ScriptQueryLine, QueryLineXuiObjectStr, QueryLineXuiSvcName> {};
+
+#endif
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiquerylist.cpp b/Src/Wasabi/api/skin/widgets/db/xuiquerylist.cpp
new file mode 100644
index 00000000..b5ff10bd
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiquerylist.cpp
@@ -0,0 +1,119 @@
+#include <precomp.h>
+#include "xuiquerylist.h"
+#include <tataki/canvas/ifc_canvas.h>
+
+#include <api/service/svcs/svc_objectdir.h>
+
+// -----------------------------------------------------------------------
+char QueryListXuiObjectStr[] = "QueryResults"; // This is the xml tag
+char QueryListXuiSvcName[] = "ScriptQueryResults xui object";
+XMLParamPair ScriptQueryList::params[] = {
+{QUERYLIST_SETTITLE, "TITLE"},
+};
+// -----------------------------------------------------------------------
+ScriptQueryList::ScriptQueryList() {
+ getScriptObject()->vcpu_setInterface(queryListGuid, (void *)static_cast<ScriptQueryList *>(this));
+#ifdef WASABI_COMPILE_METADB
+ getScriptObject()->vcpu_setInterface(multiQueryServerGuid, (void *)static_cast<MultiQueryServer *>(this));
+#endif
+ getScriptObject()->vcpu_setClassName("QueryList"); // this is the script class name
+ getScriptObject()->vcpu_setController(queryListController);
+
+ myxuihandle = newXuiHandle();
+
+ int numParams = sizeof(params) / sizeof(params[0]);
+ hintNumberOfParams(numParams);
+ for (int i = 0;i < numParams;i++)
+ addParam(myxuihandle, params[i], XUI_ATTRIBUTE_IMPLIED);
+}
+
+ScriptQueryList::~ScriptQueryList() {
+}
+
+// -----------------------------------------------------------------------
+int ScriptQueryList::setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value) {
+ if (xuihandle != myxuihandle)
+ return QUERYLIST_PARENT::setXuiParam(xuihandle, xmlattributeid, xmlattributename, value);
+
+ switch (xmlattributeid) {
+ case QUERYLIST_SETTITLE: setTitle(value); break;
+ default: return 0;
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+void ScriptQueryList::setTitle(const char *name) {
+ setName(name);
+//CUT if (!name || !*name) showLabel(0); else showLabel(1);
+}
+
+#ifdef WASABI_COMPILE_METADB
+// -----------------------------------------------------------------------
+void ScriptQueryList::onResetSubqueries() {
+ QUERYLIST_PARENT::onResetSubqueries();
+ QueryListScriptController::querylist_onResetQuery(SCRIPT_CALL, getScriptObject());
+}
+#endif
+
+#ifdef WASABI_COMPILE_METADB
+int ScriptQueryList::onAction(const char *action, const char *param, int x, int y, intptr_t p1, intptr_t p2, void *data, size_t datalen, api_window *source) {
+ if (STRCASEEQLSAFE(action, "SAVEQUERY")) {
+ String q = mqs_getMultiQuery();
+ if (!q.isempty()) {
+ svc_objectDir *qd = ObjectDirEnum("querydir").getNext();
+ if (qd != NULL) {
+ qd->insertObject(q, "gay", "user is gay");
+ }
+ }
+ return 1;
+ }
+ return QUERYLIST_PARENT::onAction(action, param, x, y, p1, p2, data, datalen, source);
+}
+#endif
+
+// -----------------------------------------------------------------------
+// Script Object
+
+QueryListScriptController _queryListController;
+QueryListScriptController *queryListController = &_queryListController;
+
+// -- Functions table -------------------------------------
+function_descriptor_struct QueryListScriptController::exportedFunction[] = {
+ {"onResetQuery", 0, (void*)QueryListScriptController::querylist_onResetQuery},
+};
+
+ScriptObject *QueryListScriptController::instantiate() {
+ ScriptQueryList *sql = new ScriptQueryList;
+ ASSERT(sql != NULL);
+ return sql->getScriptObject();
+}
+
+void QueryListScriptController::destroy(ScriptObject *o) {
+ ScriptQueryList *sql = static_cast<ScriptQueryList *>(o->vcpu_getInterface(queryListGuid));
+ ASSERT(sql != NULL);
+ delete sql;
+}
+
+void *QueryListScriptController::encapsulate(ScriptObject *o) {
+ return NULL; // no encapsulation for querylist yet
+}
+
+void QueryListScriptController::deencapsulate(void *o) {
+}
+
+int QueryListScriptController::getNumFunctions() {
+ return sizeof(exportedFunction) / sizeof(function_descriptor_struct);
+}
+
+const function_descriptor_struct *QueryListScriptController::getExportedFunctions() {
+ return exportedFunction;
+}
+
+
+scriptVar QueryListScriptController::querylist_onResetQuery(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
+ SCRIPT_FUNCTION_INIT;
+ PROCESS_HOOKS0(o, queryListController);
+ SCRIPT_FUNCTION_CHECKABORTEVENT;
+ SCRIPT_EXEC_EVENT0(o);
+}
diff --git a/Src/Wasabi/api/skin/widgets/db/xuiquerylist.h b/Src/Wasabi/api/skin/widgets/db/xuiquerylist.h
new file mode 100644
index 00000000..a278afcb
--- /dev/null
+++ b/Src/Wasabi/api/skin/widgets/db/xuiquerylist.h
@@ -0,0 +1,72 @@
+#ifndef __QUERYLIST_H
+#define __QUERYLIST_H
+
+#include <api/wnd/wndclass/guiobjwnd.h>
+#ifdef WASABI_COMPILE_METADB
+#include <api/skin/widgets/db/autoquerylist.h>
+#endif
+#include <api/script/objcontroller.h>
+
+#ifdef WASABI_COMPILE_METADB
+#define QUERYLIST_PARENT AutoQueryList
+#else
+#define QUERYLIST_PARENT GuiObjectWnd
+#endif
+
+// -----------------------------------------------------------------------
+class ScriptQueryList : public QUERYLIST_PARENT {
+
+ public:
+
+ ScriptQueryList();
+ virtual ~ScriptQueryList();
+
+ virtual int setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value);
+
+ void setTitle(const char *name);
+
+#ifdef WASABI_COMPILE_METADB
+ void onResetSubqueries();
+ virtual int onAction(const wchar_t *action, const wchar_t *param=NULL, int x=-1, int y=-1, intptr_t p1=0, intptr_t p2=0, void *data=NULL, size_t datalen=0, api_window *source=NULL);
+#endif
+
+ private:
+
+ enum {
+ QUERYLIST_SETTITLE = 0,
+ };
+ static XMLParamPair params[];
+ int myxuihandle;
+};
+
+// -----------------------------------------------------------------------
+class QueryListScriptController: public ScriptObjectControllerI {
+ public:
+
+ virtual const wchar_t *getClassName() { return L"QueryList"; }
+ virtual const wchar_t *getAncestorClassName() { return L"GuiObject"; }
+ virtual ScriptObjectController *getAncestorController() { return WASABI_API_MAKI->maki_getController(guiObjectGuid); }
+ virtual int getNumFunctions();
+ virtual const function_descriptor_struct *getExportedFunctions();
+ virtual GUID getClassGuid() { return queryListGuid; }
+ virtual ScriptObject *instantiate();
+ virtual void destroy(ScriptObject *o);
+ virtual void *encapsulate(ScriptObject *o);
+ virtual void deencapsulate(void *o);
+
+ static scriptVar querylist_onResetQuery(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+
+ private:
+
+ static function_descriptor_struct exportedFunction[];
+
+};
+
+extern QueryListScriptController *queryListController;
+
+// -----------------------------------------------------------------------
+extern char QueryListXuiObjectStr[];
+extern char QueryListXuiSvcName[];
+class QueryListXuiSvc : public XuiObjectSvc<ScriptQueryList, QueryListXuiObjectStr, QueryListXuiSvcName> {};
+
+#endif