From 50b5a4231c40904dc9dd19939c6f7502400360bb Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Tue, 3 Aug 2021 11:24:40 +0800 Subject: [PATCH 1/8] Add Tibetan in desktop file. --- data/ukui-search-menu.desktop | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/ukui-search-menu.desktop b/data/ukui-search-menu.desktop index 085b75c..d9dc4b1 100644 --- a/data/ukui-search-menu.desktop +++ b/data/ukui-search-menu.desktop @@ -1,10 +1,13 @@ [Desktop Entry] Name=Search Name[zh_CN]=搜索 +Name[bo_CN]=བཤེར་འཚོལ། GenericName=UKUI Global Search GenericName[zh_CN]=全局搜索 +GenericName[bo_CN]=བཤེར་འཚོལ། Comment=ukui-search Comment[zh_CN]=全局搜索 +Comment[bo_CN]=ཁྱོན་ཡོངས་བཤེར་འཚོལ། Exec=/usr/bin/ukui-search -s Type=Application Icon=kylin-search From 27da9f3a0ea7df373e714c6fbf888ac62e934c86 Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Wed, 11 Aug 2021 09:34:32 +0800 Subject: [PATCH 2/8] Update app search. --- libsearch/appsearch/app-match.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsearch/appsearch/app-match.cpp b/libsearch/appsearch/app-match.cpp index 8ad8d31..3196c65 100644 --- a/libsearch/appsearch/app-match.cpp +++ b/libsearch/appsearch/app-match.cpp @@ -344,8 +344,7 @@ void AppMatch::parseSoftWareCenterReturn(QList> list, QMa if(locale.language() == QLocale::Chinese) { appname = list.at(i).value("displayname_cn"); pkgname = list.at(i).value("appname"); - } - if(locale.language() == QLocale::English) { + }else { appname = list.at(i).value("appname"); } appdiscription = list.at(i).value("discription"); From cdc03035c28b96498066f75ff1f34a288b6f8fe1 Mon Sep 17 00:00:00 2001 From: "baijunjie@kylinos.cn" Date: Wed, 11 Aug 2021 13:57:54 +0800 Subject: [PATCH 3/8] use dbus interface to show the ukui-search window --- src/main.cpp | 2 ++ src/src.pro | 2 ++ src/ukui-search-dbus-service.cpp | 22 ++++++++++++++++++++++ src/ukui-search-dbus-service.h | 28 ++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 src/ukui-search-dbus-service.cpp create mode 100644 src/ukui-search-dbus-service.h diff --git a/src/main.cpp b/src/main.cpp index 37674a2..04bdb83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,6 +39,7 @@ //#include "inotify-manager.h" #include "libsearch.h" #include "global-settings.h" +#include "ukui-search-dbus-service.h" using namespace Zeeker; //void handler(int){ @@ -279,6 +280,7 @@ int main(int argc, char *argv[]) { //set main window to the center of screen MainWindow *w = new MainWindow; + UkuiSearchDbusServices dbusService(w); qApp->setWindowIcon(QIcon::fromTheme("kylin-search")); // centerToScreen(w); // w->moveToPanel(); diff --git a/src/src.pro b/src/src.pro index f61b5a7..fd8f22c 100644 --- a/src/src.pro +++ b/src/src.pro @@ -34,6 +34,7 @@ SOURCES += \ search-app-thread.cpp \ search-result.cpp \ settings-widget.cpp \ + ukui-search-dbus-service.cpp \ xatom-helper.cpp @@ -45,6 +46,7 @@ HEADERS += \ search-app-thread.h \ search-result.h \ settings-widget.h \ + ukui-search-dbus-service.h \ xatom-helper.h # Default rules for deployment. diff --git a/src/ukui-search-dbus-service.cpp b/src/ukui-search-dbus-service.cpp new file mode 100644 index 0000000..5ca1981 --- /dev/null +++ b/src/ukui-search-dbus-service.cpp @@ -0,0 +1,22 @@ +#include "ukui-search-dbus-service.h" + +using namespace Zeeker; +void UkuiSearchDbusServices::showWindow(){ + m_mainWindow->bootOptionsFilter("-s"); +} + +UkuiSearchDbusServices::UkuiSearchDbusServices(MainWindow *m) +{ + m_mainWindow = m; + //注册服务 + QDBusConnection sessionBus = QDBusConnection::sessionBus(); + if(!sessionBus.registerService("org.ukui.search.service")){ + qWarning() << "ukui-search dbus register service failed reason:" << sessionBus.lastError(); + } + + if(!sessionBus.registerObject("/", this, QDBusConnection::ExportAllSlots)){ + qWarning() << "ukui-search dbus register object failed reason:" << sessionBus.lastError(); + } +} +UkuiSearchDbusServices::~UkuiSearchDbusServices(){ +} diff --git a/src/ukui-search-dbus-service.h b/src/ukui-search-dbus-service.h new file mode 100644 index 0000000..d02ba87 --- /dev/null +++ b/src/ukui-search-dbus-service.h @@ -0,0 +1,28 @@ +#ifndef UKUISEARCHDBUSSERVICE_H +#define UKUISEARCHDBUSSERVICE_H + +#include +#include + +#include "mainwindow.h" + +namespace Zeeker { + +class UkuiSearchDbusServices: public QObject{ + Q_OBJECT + + Q_CLASSINFO("D-Bus Interface","org.ukui.search.service") + +public: + explicit UkuiSearchDbusServices(MainWindow *m); + ~UkuiSearchDbusServices(); + +public Q_SLOTS: + void showWindow(); + +private: + MainWindow *m_mainWindow; +}; +} + +#endif // UKUISEARCHDBUSSERVICE_H From 95975b75386e38d91a9fb5dee477cc6c310f4746 Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Fri, 13 Aug 2021 11:20:31 +0800 Subject: [PATCH 4/8] Update MainWindow::centerToScreen. --- src/mainwindow.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cf80e43..9f13cd4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -471,16 +471,16 @@ void MainWindow::centerToScreen(QWidget* widget) { int desk_y = desk_rect.height(); int x = widget->width(); int y = widget->height(); - QDBusInterface primaryScreenInterface("org.ukui.SettingsDaemon", - "/org/ukui/SettingsDaemon/wayland", - "org.ukui.SettingsDaemon.wayland", - QDBusConnection::sessionBus()); - if(QDBusReply(primaryScreenInterface.call("x")).isValid()) { - QDBusReply width = primaryScreenInterface.call("width"); - QDBusReply height = primaryScreenInterface.call("height"); - desk_x = width; - desk_y = height; - } +// QDBusInterface primaryScreenInterface("org.ukui.SettingsDaemon", +// "/org/ukui/SettingsDaemon/wayland", +// "org.ukui.SettingsDaemon.wayland", +// QDBusConnection::sessionBus()); +// if(QDBusReply(primaryScreenInterface.call("x")).isValid()) { +// QDBusReply width = primaryScreenInterface.call("width"); +// QDBusReply height = primaryScreenInterface.call("height"); +// desk_x = width; +// desk_y = height; +// } widget->move(desk_x / 2 - x / 2 + desk_rect.left(), desk_y / 2 - y / 2 + desk_rect.top()); } From c8e9ec5134d374bd9485cb550da47d7201c50a2d Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Fri, 13 Aug 2021 16:27:59 +0800 Subject: [PATCH 5/8] Update dbus interface. --- src/input-box.cpp | 6 +++--- src/input-box.h | 10 +++++----- src/ukui-search-dbus-service.cpp | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/input-box.cpp b/src/input-box.cpp index 1d3fcba..0b57c19 100644 --- a/src/input-box.cpp +++ b/src/input-box.cpp @@ -235,9 +235,9 @@ SearchLineEdit::SearchLineEdit(QWidget *parent) : QLineEdit(parent) { // this->addAction(searchAction,QLineEdit::LeadingPosition); /*发送输入框文字改变的dbus*/ - QDBusConnection::sessionBus().unregisterService("org.ukui.search.service"); - QDBusConnection::sessionBus().registerService("org.ukui.search.service"); - QDBusConnection::sessionBus().registerObject("/lineEdit/textChanged", this, QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals); +// QDBusConnection::sessionBus().unregisterService("org.ukui.search.service"); +// QDBusConnection::sessionBus().registerService("org.ukui.search.service"); +// QDBusConnection::sessionBus().registerObject("/lineEdit/textChanged", this, QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals); connect(this, &QLineEdit::textChanged, this, &SearchLineEdit::lineEditTextChanged); connect(this, &QLineEdit::textChanged, this, [ = ]() { diff --git a/src/input-box.h b/src/input-box.h index d17db8c..61e4973 100644 --- a/src/input-box.h +++ b/src/input-box.h @@ -94,11 +94,11 @@ private: class SearchLineEdit : public QLineEdit { Q_OBJECT - /* - * 负责与ukui桌面环境应用通信的dbus - * 搜索框文本改变的时候发送信号 -    */ - Q_CLASSINFO("D-Bus Interface", "org.ukui.search.inputbox") +// /* +// * 负责与ukui桌面环境应用通信的dbus +// * 搜索框文本改变的时候发送信号 +//    */ +// Q_CLASSINFO("D-Bus Interface", "org.ukui.search.inputbox") public: SearchLineEdit(QWidget *parent = nullptr); void record(); diff --git a/src/ukui-search-dbus-service.cpp b/src/ukui-search-dbus-service.cpp index 5ca1981..c0955af 100644 --- a/src/ukui-search-dbus-service.cpp +++ b/src/ukui-search-dbus-service.cpp @@ -10,7 +10,8 @@ UkuiSearchDbusServices::UkuiSearchDbusServices(MainWindow *m) m_mainWindow = m; //注册服务 QDBusConnection sessionBus = QDBusConnection::sessionBus(); - if(!sessionBus.registerService("org.ukui.search.service")){ + QDBusConnection::sessionBus().unregisterService("com.ukui.search.service"); + if(!sessionBus.registerService("com.ukui.search.service")){ qWarning() << "ukui-search dbus register service failed reason:" << sessionBus.lastError(); } From 359af667fc9e7a9838d81ce9382f9736c39d3669 Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Thu, 19 Aug 2021 10:45:51 +0800 Subject: [PATCH 6/8] Update pinyinWithoutTone.txt. --- libsearch/index/first-index.cpp | 17 ++------------ libsearch/index/first-index.h | 22 ------------------- libsearch/index/pinyinWithoutTone.txt | 4 ++-- .../ukuisearch-systemdbus.pro | 2 +- 4 files changed, 5 insertions(+), 40 deletions(-) diff --git a/libsearch/index/first-index.cpp b/libsearch/index/first-index.cpp index 15f6429..59a44b1 100644 --- a/libsearch/index/first-index.cpp +++ b/libsearch/index/first-index.cpp @@ -95,9 +95,7 @@ void FirstIndex::DoSomething(const QFileInfo& fileInfo) { void FirstIndex::run() { QTime t1 = QTime::currentTime(); - // Create a fifo at ~/.config/org.ukui/ukui-search, the fifo is used to control the order of child processes' running. - QString indexDataBaseStatus = IndexStatusRecorder::getInstance()->getStatus(INDEX_DATABASE_STATE).toString(); QString contentIndexDataBaseStatus = IndexStatusRecorder::getInstance()->getStatus(CONTENT_INDEX_DATABASE_STATE).toString(); QString inotifyIndexStatus = IndexStatusRecorder::getInstance()->getStatus(INOTIFY_NORMAL_EXIT).toString(); @@ -106,7 +104,6 @@ void FirstIndex::run() { qDebug() << "contentIndexDataBaseStatus: " << contentIndexDataBaseStatus; qDebug() << "inotifyIndexStatus: " << inotifyIndexStatus; - /* || contentIndexDataBaseStatus == ""*/ if(indexDataBaseStatus == "") { this->bool_dataBaseExist = false; } else { @@ -119,9 +116,6 @@ void FirstIndex::run() { } this->q_index = new QQueue>(); - //this->q_content_index = new QQueue(); - //NEW_QUEUE(this->q_content_index); -// this->mlm = new MessageListManager(); this->q_content_index = new QQueue>(); int fifo_fd; @@ -135,11 +129,6 @@ void FirstIndex::run() { assert(false); } -// this->q_content_index->enqueue(QString("/home/zhangzihao/Desktop/qwerty/四库全书.txt")); - -// this->p_indexGenerator->creatAllIndex(this->q_content_index); - - ++FileUtils::_index_status; pid_t pid; pid = fork(); @@ -157,7 +146,6 @@ void FirstIndex::run() { } else { // p_indexGenerator = IndexGenerator::getInstance(false,this); p_indexGenerator = IndexGenerator::getInstance(true, this); - } //TODO Fix these weird code. QSemaphore sem(5); @@ -166,7 +154,6 @@ void FirstIndex::run() { mutex2.lock(); mutex3.lock(); sem.acquire(4); -// QtConcurrent::run([&](){ sem.acquire(1); mutex1.unlock(); this->setPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); @@ -174,7 +161,6 @@ void FirstIndex::run() { FileUtils::_max_index_count = this->q_index->length(); qDebug() << "max_index_count:" << FileUtils::_max_index_count; sem.release(5); -// }); QtConcurrent::run(&m_pool, [&]() { sem.acquire(2); mutex2.unlock(); @@ -197,7 +183,6 @@ void FirstIndex::run() { QQueue* tmp2 = new QQueue(); qDebug() << "q_content_index:" << q_content_index->size(); while(!this->q_content_index->empty()) { - // for (size_t i = 0; (i < this->u_send_length) && (!this->q_content_index->empty()); ++i){ qint64 fileSize = 0; //修改一次处理的数据量,从30个文件改为文件总大小为50M以下,50M为暂定值--jxx20210519 for(size_t i = 0;/* (i < 30) && (fileSize < 52428800) && */(!this->q_content_index->empty()); ++i) { @@ -230,6 +215,8 @@ void FirstIndex::run() { mutex2.unlock(); mutex3.unlock(); + + if(this->q_index) delete this->q_index; this->q_index = nullptr; diff --git a/libsearch/index/first-index.h b/libsearch/index/first-index.h index ab1d23e..9275260 100644 --- a/libsearch/index/first-index.h +++ b/libsearch/index/first-index.h @@ -35,11 +35,9 @@ #include #include #include -//#include #include "traverse_bfs.h" #include "index-status-recorder.h" #include "index-generator.h" -#include "inotify-index.h" #include "file-utils.h" #include "common.h" namespace Zeeker { @@ -58,31 +56,11 @@ private: IndexGenerator* p_indexGenerator = nullptr; QThreadPool m_pool; - //here should be refact -// MessageListManager* mlm; - - //test QQueue>* q_index; // QQueue* q_content_index; //修改QQueue存储数据为QPair,增加存储文件大小数据便于处理时统计--jxx20210519 QQueue>* q_content_index; - const QMap targetFileTypeMap = { - std::map::value_type("doc", true), - std::map::value_type("docx", true), - std::map::value_type("ppt", true), - std::map::value_type("pptx", true), - std::map::value_type("xls", true), - std::map::value_type("xlsx", true), - std::map::value_type("txt", true), - std::map::value_type("dot", true), - std::map::value_type("wps", true), - std::map::value_type("pps", true), - std::map::value_type("dps", true), - std::map::value_type("et", true), - std::map::value_type("pdf", true) - }; - //xapian will auto commit per 10,000 changes, donnot change it!!! const size_t u_send_length = 8192; }; diff --git a/libsearch/index/pinyinWithoutTone.txt b/libsearch/index/pinyinWithoutTone.txt index 5477369..5c1af9c 100644 --- a/libsearch/index/pinyinWithoutTone.txt +++ b/libsearch/index/pinyinWithoutTone.txt @@ -7280,7 +7280,7 @@ jiao 叫 shao,zhao 召 ba,pa 叭 ding 叮 -ke,ge 可 +ke 可 tai,yi,si 台 chi,hua,e 叱 shi 史 @@ -8647,7 +8647,7 @@ di,ti 奃 yan 奄 pao 奅 juan 奆 -ji,ai,yi,qi 奇 +ji,qi 奇 nai 奈 feng 奉 pi,xi,lie,xie 奊 diff --git a/ukuisearch-systemdbus/ukuisearch-systemdbus.pro b/ukuisearch-systemdbus/ukuisearch-systemdbus.pro index 8ceb141..623a8b5 100644 --- a/ukuisearch-systemdbus/ukuisearch-systemdbus.pro +++ b/ukuisearch-systemdbus/ukuisearch-systemdbus.pro @@ -22,7 +22,7 @@ target.path = /usr/bin INSTALLS += \ target \ inst1 \ - inst2 \ + inst2 HEADERS += \ sysdbusregister.h From a7e296ca0c6239bd0c36bf256c600b09e59df543 Mon Sep 17 00:00:00 2001 From: baijunjie Date: Fri, 20 Aug 2021 10:10:46 +0800 Subject: [PATCH 7/8] fix the question that the keyword will be cut off in the resultPage of the file content search. --- libsearch/file-utils.cpp | 66 ++++++++++++++++++++++++++++++ libsearch/file-utils.h | 3 ++ libsearch/index/search-manager.cpp | 34 ++++++++------- 3 files changed, 88 insertions(+), 15 deletions(-) diff --git a/libsearch/file-utils.cpp b/libsearch/file-utils.cpp index 113fbf5..98789a0 100644 --- a/libsearch/file-utils.cpp +++ b/libsearch/file-utils.cpp @@ -773,3 +773,69 @@ void FileUtils::getTxtContent(QString &path, QString &textcontent) { return; } + +QString FileUtils::chineseSubString(const std::string &data, int start, int length) +{ + std::string afterSub = ""; + //越界保护 + if(start < 0 || length < 0){ + return " "; + } + if (length >= data.length()) { + return QString::fromStdString(data); + } + + QString snippet = ""; + QFont ft(QApplication::font().family(),QApplication::font().pointSize()); + QFontMetrics fm (ft); + + if (start + length <= data.length()) { + afterSub = data.substr(start,length); //截取 + snippet = QString::fromStdString(afterSub); //转QString + + if(start + length < data.length()){ + snippet.replace(snippet.length()-3,3,"..."); //替换后三位 + } + snippet = fm.elidedText(snippet, Qt::ElideRight, 2*366); //超过两行则省略 + } else { + int newStart = data.length()-length; //更新截取位置 + int bodyByteCount = 0; + int letterCount = 0; + + for(int i = newStart;i > 0;i--){ + if(data[i] & 0x80) { + char tmp = data[i] << 1; + if(tmp & 0x80){ + break; + } else { + bodyByteCount++; + } + + } else { + letterCount++; + if(letterCount == 3) { + break; + } + + } + } + int correctionValue = letterCount + (bodyByteCount); + afterSub = data.substr(newStart - correctionValue, length + correctionValue); + snippet=QString::fromStdString(afterSub); + + switch(letterCount) + { + case 0: + snippet.replace(0,1,".").prepend(".."); + break; + case 1: + snippet.replace(0,2,"..").prepend("."); + break; + default: + snippet.replace(0,3,"..."); + } + + snippet = fm.elidedText(snippet, Qt::ElideLeft, 2*500); + } + return snippet; +} diff --git a/libsearch/file-utils.h b/libsearch/file-utils.h index f0a9085..b3ef3ae 100644 --- a/libsearch/file-utils.h +++ b/libsearch/file-utils.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -83,6 +85,7 @@ public: static void getXlsxTextContent(QString &path, QString &textcontent); static void getPdfTextContent(QString &path, QString &textcontent); static void getTxtContent(QString &path, QString &textcontent); + static QString chineseSubString(const std::string &data, int start, int length); static size_t _max_index_count; static size_t _current_index_count; //this one has been Abandoned,do not use it. static unsigned short _index_status; diff --git a/libsearch/index/search-manager.cpp b/libsearch/index/search-manager.cpp index c501594..09edbf1 100644 --- a/libsearch/index/search-manager.cpp +++ b/libsearch/index/search-manager.cpp @@ -338,22 +338,26 @@ int FileContentSearch::getResult(Xapian::MSet &result, std::string &keyWord) { // qWarning()< 6 + QString::fromStdString(keyWord).size()) { - snippet.replace(0, 3, "...").replace(snippet.size() - 3, 3, "..."); - } else { - snippet.append("...").prepend("..."); - } - snippets.append(snippet); - QString().swap(snippet); - std::string().swap(s); - ++count; - } + auto pos = term.positionlist_begin(); + int length = 120; + QString snippet = FileUtils::chineseSubString(data,*pos,length); +// int count = 0; +// for(auto pos = term.positionlist_begin(); pos != term.positionlist_end() && count < 6; ++pos) { +// std::string s = data.substr((*pos < 60) ? 0 : (*pos - 60), size + 120); +// QString snippet = QString::fromStdString(s); +// if(snippet.size() > 6 + QString::fromStdString(keyWord).size()) { +// snippet.replace(0, 3, "...").replace(snippet.size() - 3, 3, "..."); +// } else { +// snippet.append("...").prepend("..."); +// } +// snippets.append(snippet); +// QString().swap(snippet); +// std::string().swap(s); +// ++count; +// } + snippets.append(snippet); std::string().swap(data); // for(QString i : QString::fromStdString(keyWord).split(" ",QString::SkipEmptyParts)) From c924d68a794784e92f8fa760bd5cd839fa5ac3b5 Mon Sep 17 00:00:00 2001 From: iaom <18504285112@163.com> Date: Fri, 20 Aug 2021 10:24:41 +0800 Subject: [PATCH 8/8] Update .gitignore. --- .gitignore | 103 +++++++++++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 62 deletions(-) diff --git a/.gitignore b/.gitignore index fab7372..f147edf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,52 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc +# C++ objects and libs +*.slo +*.lo *.o -*.obj -*.orig -*.rej +*.a +*.la +*.lai *.so *.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc +*.dll +*.dylib + +# Qt-es +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp /.qmake.cache /.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* +*.qm +*.prl -# qtcreator generated files -*.pro.user* +# Qt unit tests +target_wrapper.* -# xemacs temporary files -*.flc +# QtCreator +*.autosave -# Vim temporary files -.*.swp +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* +# QtCreator CMake +CMakeLists.txt.user* -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe +# QtCreator 4.8< compilation database +compile_commands.json +# QtCreator local machine specific files for imported projects +*creator.user*