return true;
}
+AnimeTitle Database::animeSearchBestMatch(const QString &query)
+{
+ QList<AnimeTitle> ret = animeSearch(query, 1);
+ if (ret.count())
+ return ret[0];
+ return AnimeTitle();
+}
+
+QList<AnimeTitle> Database::animeSearch(const QString &query, int limit)
+{
+ QList<AnimeTitle> ret;
+
+ QSqlQuery &q = prepare(
+ "SELECT at.title_id, at.aid, at.type, at.language, at.title "
+ " FROM anime_title at "
+ " WHERE at.title ILIKE :query "
+ " ORDER BY at.title <-> :query2 ASC "
+ " LIMIT :limit");
+ q.bindValue(":query", query);
+ q.bindValue(":query2", query);
+ q.bindValue(":limit", limit);
+
+ if (!exec(q))
+ return ret;
+
+ QSqlResultIterator it(q);
+ while (q.next())
+ {
+ AnimeTitle data;
+ readAnimeTitleData(it, data);
+ ret << data;
+ }
+
+ q.finish();
+
+ return ret;
+}
+
+QList<AnimeTitle> Database::animeSearchSimmilar(const QString &query, int limit)
+{
+ QList<AnimeTitle> ret;
+
+ QSqlQuery &q = prepare(
+ "SELECT at.title_id, at.aid, at.type, at.language, at.title "
+ " FROM anime_title at "
+ " ORDER BY at.title <-> :query ASC "
+ " LIMIT :limit");
+ q.bindValue(":query", query);
+ q.bindValue(":limit", limit);
+
+ if (!exec(q))
+ return ret;
+
+ QSqlResultIterator it(q);
+ while (q.next())
+ {
+ AnimeTitle data;
+ readAnimeTitleData(it, data);
+ ret << data;
+ }
+
+ q.finish();
+
+ return ret;
+}
+
OpenFileData Database::firstUnwatchedByExactTitle(const QString &title)
{
QSqlQuery &q = prepare(
data.titleId = result.value(offset++).toInt();
data.aid = result.value(offset++).toInt();
data.type = AnimeTitle::TitleType(result.value(offset++).toInt());
- data.language = result.value(offset++).toString();
+ data.language = result.value(offset++).toString().trimmed();
data.title = result.value(offset++).toString();
}
c = true;
}
+QString toSearchQuery(const QString &string)
+{
+ const static QChar anyChar = QChar('%');
+ QString ret = string.trimmed();
+ ret.replace(QRegExp("\\s+"), anyChar);
+ ret = ret.append(anyChar).prepend(anyChar);
+ return ret;
+}
+
} // namespace LocalMyList
bool commit();
bool rollback();
+ LocalMyList::AnimeTitle animeSearchBestMatch(const QString &query);
+ QList<LocalMyList::AnimeTitle> animeSearch(const QString &query, int limit = 100);
+ QList<LocalMyList::AnimeTitle> animeSearchSimmilar(const QString &query, int limit = 5);
+
LocalMyList::OpenFileData firstUnwatchedByExactTitle(const QString &title);
LocalMyList::OpenFileData firstUnwatchedByTitle(const QString &title);
LocalMyList::OpenFileData firstUnwatchedByAid(int aid);
void commit();
};
+QString toSearchQuery(const QString &string);
+
} // namespace LocalMyList
Q_DECLARE_METATYPE(LocalMyList::Database*)
} // namespace LocalMyList
+Q_DECLARE_METATYPE(LocalMyList::AnimeTitle)
+Q_DECLARE_METATYPE(LocalMyList::AnimeTitle*)
+Q_DECLARE_METATYPE(QList<LocalMyList::AnimeTitle>)
+Q_DECLARE_METATYPE(QList<LocalMyList::AnimeTitle*>)
Q_DECLARE_METATYPE(LocalMyList::Anime)
Q_DECLARE_METATYPE(LocalMyList::Anime*)
Q_DECLARE_METATYPE(QList<LocalMyList::Anime>)
qScriptRegisterMetaType<Database*>(engine, Scriptable::toScriptValue<Database*>, Scriptable::fromScriptValue<Database*>);
qScriptRegisterMetaType<Settings*>(engine, Scriptable::toScriptValue<Settings*>, Scriptable::fromScriptValue<Settings*>);
+ engine->globalObject().setProperty("toSearchQuery", engine->newFunction(Scriptable::toSearchQuery));
+
+ Scriptable::AnimeTitle *AnimeTitlePrototype = new Scriptable::AnimeTitle();
+ engine->setDefaultPrototype(qMetaTypeId<AnimeTitle>(), engine->newQObject(AnimeTitlePrototype));
+ engine->setDefaultPrototype(qMetaTypeId<AnimeTitle*>(), engine->newQObject(AnimeTitlePrototype));
+ qScriptRegisterSequenceMetaType<QList<AnimeTitle> >(engine);
+ qScriptRegisterSequenceMetaType<QList<AnimeTitle*> >(engine);
Scriptable::Anime *AnimePrototype = new Scriptable::Anime();
engine->setDefaultPrototype(qMetaTypeId<Anime>(), engine->newQObject(AnimePrototype));
engine->setDefaultPrototype(qMetaTypeId<Anime*>(), engine->newQObject(AnimePrototype));
namespace Scriptable {
+::LocalMyList::AnimeTitle *AnimeTitle::thisObj() const
+{
+ return qscriptvalue_cast< ::LocalMyList::AnimeTitle*>(thisObject());
+}
+
+AnimeTitle::AnimeTitle(QObject *parent) : QObject(parent), QScriptable()
+{
+}
+
+QString titleTypeToString(int titleType)
+{
+ switch (::LocalMyList::AnimeTitle::TitleType(titleType))
+ {
+ case ::LocalMyList::AnimeTitle::PrimaryTitle:
+ return "Primary";
+ case ::LocalMyList::AnimeTitle::OfficialTitle:
+ return "Official";
+ case ::LocalMyList::AnimeTitle::ShortTitle:
+ return "Short";
+ case ::LocalMyList::AnimeTitle::Synonym:
+ return "Synonym";
+ }
+ return "Unknown";
+}
+
+QString AnimeTitle::toString() const
+{
+ return QString("AnimeTitle('%1', %2, %3, %4)")
+ .arg(read_title()).arg(read_language())
+ .arg(titleTypeToString(read_type())).arg(read_aid());
+}
+
+// --------------------------------------------------------------------------------
+
::LocalMyList::Anime *Anime::thisObj() const
{
return qscriptvalue_cast< ::LocalMyList::Anime*>(thisObject());
// Generated
// --------------------------------------------------------------------------------
+int AnimeTitle::read_aid() const
+{
+ auto o = thisObj();
+ if (!o) return int();
+ return o->aid;
+}
+
+void AnimeTitle::write_aid(int val)
+{
+ auto o = thisObj();
+ if (!o) return;
+ o->aid = val;
+}
+
+int AnimeTitle::read_type() const
+{
+ auto o = thisObj();
+ if (!o) return int();
+ return int(o->type);
+}
+
+void AnimeTitle::write_type(int val)
+{
+ auto o = thisObj();
+ if (!o) return;
+ o->type = ::LocalMyList::AnimeTitle::TitleType(val);
+}
+
+QString AnimeTitle::read_language() const
+{
+ auto o = thisObj();
+ if (!o) return QString();
+ return o->language;
+}
+
+void AnimeTitle::write_language(QString val)
+{
+ auto o = thisObj();
+ if (!o) return;
+ o->language = val;
+}
+
+QString AnimeTitle::read_title() const
+{
+ auto o = thisObj();
+ if (!o) return QString();
+ return o->title;
+}
+
+void AnimeTitle::write_title(QString val)
+{
+ auto o = thisObj();
+ if (!o) return;
+ o->title = val;
+}
+
+// --------------------------------------------------------------------------------
+
int Anime::read_aid() const
{
auto o = thisObj();
return engine->toScriptValue(::LocalMyList::DatabaseConnectionSettings());
}
+QScriptValue toSearchQuery(QScriptContext *ctx, QScriptEngine *engine)
+{
+ if (!ctx->argumentCount())
+ return engine->toScriptValue(QString());
+ return engine->toScriptValue(::LocalMyList::toSearchQuery(ctx->argument(0).toString()));
+}
+
} // namespace Scriptable
} // namespace LocalMyList
namespace LocalMyList {
+struct AnimeTitle;
struct Anime;
struct Episode;
struct File;
t = qobject_cast<T>(value.toQObject());
}
-/*
-struct LOCALMYLISTSHARED_EXPORT AnimeTitle
+struct LOCALMYLISTSHARED_EXPORT AnimeTitle : public QObject, protected QScriptable
{
- enum TitleType {
- PrimaryTitle = 1,
- Synonym = 2,
- ShortTitle = 3,
- OfficialTitle = 4
- };
-
- int aid;
- TitleType type;
- QString language;
- QString title;
-
- AnimeTitle(int aid = 0, TitleType type = PrimaryTitle, const QString &language = QString(), const QString &title = QString());
+ Q_OBJECT
+ Q_PROPERTY(int aid READ read_aid WRITE write_aid)
+ Q_PROPERTY(int type READ read_type WRITE write_type)
+ Q_PROPERTY(QString language READ read_language WRITE write_language)
+ Q_PROPERTY(QString title READ read_title WRITE write_title)
+
+ ::LocalMyList::AnimeTitle *thisObj() const;
+
+public:
+ AnimeTitle(QObject *parent = 0);
+
+public slots:
+ QString toString() const;
+
+public:
+ int read_aid() const;
+ void write_aid(int val);
+
+ int read_type() const;
+ void write_type(int val);
+
+ QString read_language() const;
+ void write_language(QString val);
+
+ QString read_title() const;
+ void write_title(QString val);
};
-*/
class LOCALMYLISTSHARED_EXPORT Anime : public QObject, protected QScriptable
{
QScriptValue OpenFileData_ctor(QScriptContext *, QScriptEngine *engine);
QScriptValue DatabaseConnectionSettings_ctor(QScriptContext *, QScriptEngine *engine);
+QScriptValue toSearchQuery(QScriptContext *, QScriptEngine *engine);
} // namespace Scriptable
} // namespace LocalMyList
CONSTRAINT unique_title UNIQUE (aid, type, language, title)
);
CREATE INDEX aid_idx ON anime_title USING btree (aid);
-CREATE INDEX title_idx ON anime_title USING gin (to_tsvector('simple'::regconfig, (title)::text));
+CREATE INDEX title_gist_trgm_idx ON anime_title USING gist (title gist_trgm_ops);
CREATE INDEX language_idx ON anime_title USING hash (language);
CREATE TABLE episode (