Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
*/

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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