diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5291a38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# C++ objects and libs +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.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-* + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator CMake +CMakeLists.txt.user* diff --git a/Display/CAboutDlg.cpp b/Display/CAboutDlg.cpp new file mode 100644 index 0000000..9615429 --- /dev/null +++ b/Display/CAboutDlg.cpp @@ -0,0 +1,10 @@ +#include "CAboutDlg.h" + +CAboutDlg::CAboutDlg(QWidget* parent) +: QDialog(parent) +{ + setupUi(this); +} + + + diff --git a/Display/CAboutDlg.h b/Display/CAboutDlg.h new file mode 100644 index 0000000..3a93b80 --- /dev/null +++ b/Display/CAboutDlg.h @@ -0,0 +1,15 @@ +#ifndef CABOUTDLG_H +#define CABOUTDLG_H + +#include +#include "ui_aboutDialog.h" + +class CAboutDlg : public QDialog, private Ui::aboutDialog +{ + Q_OBJECT + +public: + CAboutDlg(QWidget* parent = 0); + virtual ~CAboutDlg() {} +}; +#endif // CABOUTDLG_H diff --git a/Display/CConfigDlg.cpp b/Display/CConfigDlg.cpp new file mode 100644 index 0000000..b02acef --- /dev/null +++ b/Display/CConfigDlg.cpp @@ -0,0 +1,186 @@ +#include +#include + +#include + +#include "CConfigDlg.h" +#include "Model/CConfigManager.h" + +CConfigDlg::CConfigDlg(QWidget* parent) +: QDialog(parent) +{ + setupUi(this); + + loadSetting(); + + // connect slot only after when dialog has already been loaded and initial content filled in + createActions(); +} + +QFont CConfigDlg::getProfileDefaultFont() +{ + return profileDefaultFont_; +} + +void CConfigDlg::loadSetting() +{ + CConfigManager* confManager; + + confManager = CConfigManager::getInstance(); + + defaultEditor_lineEdit->setText(confManager->getAppSettingValue("DefaultEditor").toString()); + tagDir_lineEdit->setText(confManager->getAppSettingValue("TagDir").toString()); + srcSubstDrv_lineEdit->setText(confManager->getAppSettingValue("SrcSubstDrv").toString()); + tagSubstDrv_lineEdit->setText(confManager->getAppSettingValue("TagSubstDrv").toString()); + tmpDir_lineEdit->setText(confManager->getAppSettingValue("TmpDir").toString()); + + timeoutRunExtProgram_lineEdit->setText(confManager->getAppSettingValue("TimeoutRunExtProgram").toString()); + + QString profileFontStr = confManager->getAppSettingValue("ProfileFont").toString(); + if (profileFontStr != "") { // load from setting + profileDefaultFont_.fromString(profileFontStr); + } else { + profileDefaultFont_ = QApplication::font(); // using application font as default font + } + + // update profile font setting display + QString fontTextToDisplay = profileDefaultFont_.family() + ", " + QString::number(profileDefaultFont_.pointSize()); + profileFont_lineEdit->setText(fontTextToDisplay); +} + +void CConfigDlg::saveSetting() +{ + CConfigManager* confManager; + + confManager = CConfigManager::getInstance(); + + confManager->setAppSettingValue("DefaultEditor", defaultEditor_lineEdit->text()); + confManager->setAppSettingValue("TagDir", tagDir_lineEdit->text()); + confManager->setAppSettingValue("SrcSubstDrv", srcSubstDrv_lineEdit->text()); + confManager->setAppSettingValue("TagSubstDrv", tagSubstDrv_lineEdit->text()); + confManager->setAppSettingValue("TmpDir", tmpDir_lineEdit->text()); + + confManager->setAppSettingValue("TimeoutRunExtProgram", timeoutRunExtProgram_lineEdit->text()); + + confManager->setAppSettingValue("ProfileFont", profileDefaultFont_.toString()); +} + +void CConfigDlg::createActions() +{ + // for different pages + connect(configListWidget, + SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), + this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*))); + + // when setting change + QObject::connect(defaultEditor_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(tagDir_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(srcSubstDrv_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(tagSubstDrv_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(tmpDir_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(timeoutRunExtProgram_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); + QObject::connect(profileFont_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(configContentChanged())); +} + +void CConfigDlg::changePage(QListWidgetItem *current, QListWidgetItem *previous) +{ + if (!current) { + current = previous; + } + + configStackedWidget->setCurrentIndex(configListWidget->row(current)); +} + +void CConfigDlg::on_okButton_clicked() +{ + on_applyButton_clicked(); + this->done(QDialog::Accepted); +} + +void CConfigDlg::on_cancelButton_clicked() +{ + this->done(QDialog::Rejected); +} + +void CConfigDlg::on_applyButton_clicked() +{ + saveSetting(); + setWindowModified(false); +} + +void CConfigDlg::configContentChanged() +{ + applyButton->setEnabled(true); + setWindowModified(true); +} + +void CConfigDlg::on_defaultEditor_toolBn_clicked() +{ + QString editorPathname; + + if (defaultEditor_lineEdit->text() != "") { + editorPathname = defaultEditor_lineEdit->text(); + } else { + editorPathname = QDir::currentPath(); + } + + QString programPath = QFileDialog::getOpenFileName(this, + tr("Default Editor"), editorPathname, tr("Program (*.exe)")); + if (programPath != "") { + defaultEditor_lineEdit->setText(programPath); + } +} + +void CConfigDlg::on_profileFont_toolBn_clicked() +{ + bool bOkClicked; + QFont selectedFont = QFontDialog::getFont( + &bOkClicked, profileDefaultFont_, this); + + if (bOkClicked) { + profileDefaultFont_ = selectedFont; + + // update profile font setting display + QString fontTextToDisplay = profileDefaultFont_.family() + ", " + QString::number(profileDefaultFont_.pointSize()); + profileFont_lineEdit->setText(fontTextToDisplay); + } + +} + +void CConfigDlg::on_tagDir_toolBn_clicked() +{ + QString tagDir; + + if (tagDir_lineEdit->text() != "") { + tagDir = tagDir_lineEdit->text(); + } else { + tagDir = QDir::currentPath(); + } + + QString directory = QFileDialog::getExistingDirectory(this, + tr("Tag directory"), tagDir); + if (directory != "") { + tagDir_lineEdit->setText(directory); + } +} + +void CConfigDlg::on_tmpDir_toolBn_clicked() +{ + QString tmpDir; + + if (tmpDir_lineEdit->text() != "") { + tmpDir = tmpDir_lineEdit->text(); + } else { + tmpDir = QDir::currentPath(); + } + + QString directory = QFileDialog::getExistingDirectory(this, + tr("Temp directory"), tmpDir); + if (directory != "") { + tmpDir_lineEdit->setText(directory); + } +} + + + + diff --git a/Display/CConfigDlg.h b/Display/CConfigDlg.h new file mode 100644 index 0000000..9766d35 --- /dev/null +++ b/Display/CConfigDlg.h @@ -0,0 +1,43 @@ +#ifndef CCONFIGDLG_H +#define CCONFIGDLG_H + +#include +#include "ui_configDialog.h" + +class CConfigDlg : public QDialog, private Ui::configDialog +{ + Q_OBJECT + +public: + CConfigDlg(QWidget* parent = 0); + + virtual ~CConfigDlg() {}; + + QFont getProfileDefaultFont(); + +private slots: + void changePage(QListWidgetItem *current, QListWidgetItem *previous); + void on_okButton_clicked(); + void on_cancelButton_clicked(); + void on_applyButton_clicked(); + + void on_defaultEditor_toolBn_clicked(); + void on_profileFont_toolBn_clicked(); + + void on_tagDir_toolBn_clicked(); + void on_tmpDir_toolBn_clicked(); + + void configContentChanged(); + +private: + void createActions(); + + void loadSetting(); + void saveSetting(); + + QFont profileDefaultFont_; + + +}; + +#endif // CCONFIGDLG_H diff --git a/Display/CEventFilterObj.cpp b/Display/CEventFilterObj.cpp new file mode 100644 index 0000000..229c89c --- /dev/null +++ b/Display/CEventFilterObj.cpp @@ -0,0 +1,79 @@ +#include +#include +#include + +#include + +#include "Display/CMainWindow.h" +#include "Model/CConfigManager.h" +#include "CEventFilterObj.h" + +bool CEventFilterObj::eventFilter(QObject *obj, QEvent *event) +{ + QPoint p; + bool bAutoHideMenu; + CConfigManager* confManager; + QKeyEvent *keyEvent; + QMouseEvent *mouseEvent; + + // only process for the key press and mouse press event + switch (event->type()) { + case QEvent::KeyPress: + case QEvent::MouseButtonPress: + break; + default: + return QObject::eventFilter(obj, event); + } + + confManager = CConfigManager::getInstance(); + + bAutoHideMenu = confManager->getAppSettingValue("AutoHideMenu").toBool(); + + // only hide/show menubar if active window is the main window + if ((bAutoHideMenu) && (strcmp(QApplication::activeWindow()->metaObject()->className(), "CMainWindow") == 0)) { + CMainWindow *mainWindow = static_cast (QApplication::activeWindow()); + + switch (event->type()) { + case QEvent::KeyPress: + keyEvent = static_cast(event); + + if (keyEvent->key() == Qt::Key_Alt) { + if (mainWindow->menuBar()->isHidden()) { + mainWindow->menuBar()->show(); + } + } else { + if (!(mainWindow->menuBar()->isHidden())) { + // only hide menu if menubar or menu not selected + if ((strcmp(QApplication::focusWidget()->metaObject()->className(), "QMenu") == -1) && + (strcmp(QApplication::focusWidget()->metaObject()->className(), "QMenuBar") == -1)) { + mainWindow->menuBar()->hide(); + } + } + } + break; + + case QEvent::MouseButtonPress: + mouseEvent = static_cast(event); + + p = mainWindow->menuBar()->mapFromGlobal(mouseEvent->globalPos()); + + // hide menuBar only when not hidden + if (!(mainWindow->menuBar()->isHidden())) { + // hide menuBar only when mouse not in menuBar area + if (!(mainWindow->menuBar()->rect().contains(p))) { + mainWindow->menuBar()->hide(); + } + } + + break; + + default: + break; + } + + return QObject::eventFilter(obj, event); + } else { + return QObject::eventFilter(obj, event); + } +} + diff --git a/Display/CEventFilterObj.h b/Display/CEventFilterObj.h new file mode 100644 index 0000000..b9d24f8 --- /dev/null +++ b/Display/CEventFilterObj.h @@ -0,0 +1,14 @@ +#ifndef CEVENTFILTEROBJ_H +#define CEVENTFILTEROBJ_H + +#include + +class CEventFilterObj : public QObject +{ + Q_OBJECT + + protected: + bool eventFilter(QObject *obj, QEvent *event); +}; + +#endif // CEVENTFILTEROBJ_H diff --git a/Display/CGroupDlg.cpp b/Display/CGroupDlg.cpp new file mode 100644 index 0000000..7d295fd --- /dev/null +++ b/Display/CGroupDlg.cpp @@ -0,0 +1,195 @@ +#include +#include + +#include +#include + +#include "CGroupDlg.h" + +CGroupDlg::CGroupDlg(QWidget* parent) +: QDialog(parent) +{ + setupUi(this); + + currentGroupName_ = ""; + + // load group list + QMap groupMap; + + CProfileManager::getInstance()->getGroupMap(groupMap); + + foreach (const CGroupItem& groupItem, groupMap) { + allGroup_comboBox->addItem(groupItem.m_name, QVariant(Qt::DisplayRole)); + } + + // default as empty for group combox box + allGroup_comboBox->setCurrentIndex(-1); + + // load all profile + + QMap profileMap; + + CProfileManager::getInstance()->getProfileMap(profileMap); + + foreach (const CProfileItem& profileItem, profileMap) { + allProfile_listWidget->addItem(profileItem.m_name); + } + + createActions(); +} + +CGroupDlg::CGroupDlg(const QString& groupName, const CGroupItem& groupItem, QWidget* parent) +: QDialog(parent) +{ + setupUi(this); + + currentGroupName_ = groupName; + + groupName_lineEdit->setText(groupItem.m_name); + labels_lineEdit->setText(groupItem.m_labels); + + // connect slot only after when CGroupDlg has already been loaded and initial content filled in + QObject::connect(groupName_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(groupContentChanged())); + QObject::connect(labels_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(groupContentChanged())); + + // fix group name comboBox + allGroup_comboBox->addItem(groupName, QVariant(Qt::DisplayRole)); + allGroup_comboBox->setEnabled(false); + + groupName_lineEdit->setText(groupName); + + // load profile for current group + loadGroupProfileListView(groupName); + + createActions(); +} + +void CGroupDlg::createActions() +{ + connect(addProfile_toolButton, SIGNAL(clicked()), this, SLOT(on_addProfileToolBn_clicked())); + connect(removeProfile_toolButton, SIGNAL(clicked()), this, SLOT(on_removeProfileToolBn_clicked())); + + connect(allGroup_comboBox, SIGNAL(activated(const QString&)), this, SLOT(on_groupComboBox_activated(const QString&))); +} + +void CGroupDlg::loadGroupProfileListView(const QString& groupName) +{ + CGroupItem groupItem; + QStringList groupProfileList; + + // remove previous item if any + includedProfile_listWidget->clear(); + allProfile_listWidget->clear(); + + // selected profile list + groupItem = CProfileManager::getInstance()->getGroupItem(groupName); + + groupProfileList = groupItem.m_profileList.split(CProfileManager::kGROUP_PROFILE_SEPERATOR, QString::SkipEmptyParts); + includedProfile_listWidget->addItems(groupProfileList); + + // not selected profile list + QMap profileMap; + + CProfileManager::getInstance()->getProfileMap(profileMap); + + foreach (const CProfileItem& profileItem, profileMap) { + if (!groupProfileList.contains(profileItem.m_name)) { + allProfile_listWidget->addItem(profileItem.m_name); + } + } +} + +void CGroupDlg::on_addProfileToolBn_clicked() +{ + QList selecedItemList = allProfile_listWidget->selectedItems(); + + foreach (QListWidgetItem* listWidgetItem, selecedItemList) { + includedProfile_listWidget->addItem(listWidgetItem->text()); + } + + qDeleteAll(selecedItemList); +} + +void CGroupDlg::on_removeProfileToolBn_clicked() +{ + QList selecedItemList = includedProfile_listWidget->selectedItems(); + + QListWidgetItem* listWidgetItem; + + foreach (listWidgetItem, selecedItemList) { + allProfile_listWidget->addItem(listWidgetItem->text()); + } + + qDeleteAll(selecedItemList); +} + +void CGroupDlg::on_okButton_clicked() +{ + on_applyButton_clicked(); + this->done(QDialog::Accepted); +} + +void CGroupDlg::on_cancelButton_clicked() +{ + this->done(QDialog::Rejected); +} + +void CGroupDlg::on_applyButton_clicked() +{ + CGroupItem modifiedItem; + QDateTime currDateTime; + + // input error checking + if (groupName_lineEdit->text() == "") { + QMessageBox::warning(this, "Group", "Group name cannot be empty!", QMessageBox::Ok); + return; + } + // labels can be empty so no checking + + modifiedItem.m_name = groupName_lineEdit->text(); + + currDateTime = QDateTime::currentDateTime(); + + modifiedItem.m_groupCreateDateTime = currDateTime.toString("dd/MM/yyyy hh:mm:ss"); + + modifiedItem.m_labels = labels_lineEdit->text(); + + // get included item list + QList includedItemList = + includedProfile_listWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard); + + QStringList updateGroupProfileList; + + foreach (QListWidgetItem* listWidgetItem, includedItemList) { + updateGroupProfileList << listWidgetItem->text(); + } + + // update profile list in item + modifiedItem.m_profileList = updateGroupProfileList.join(CProfileManager::kGROUP_PROFILE_SEPERATOR); + + if (currentGroupName_ == "") { // new Group + CProfileManager::getInstance()->updateGroupItem(modifiedItem.m_name, modifiedItem); + } else { + // use currentGroupName_ for updateProfileItem as name may have be changed + CProfileManager::getInstance()->updateGroupItem(currentGroupName_, modifiedItem); + } + + setWindowModified(false); +} + +void CGroupDlg::on_groupComboBox_activated(const QString& comboText) +{ + groupName_lineEdit->setText(comboText); + + // load profile for current group + loadGroupProfileListView(comboText); +} + + +void CGroupDlg::groupContentChanged() +{ + applyButton->setEnabled(true); + setWindowModified(true); +} + + diff --git a/Display/CGroupDlg.h b/Display/CGroupDlg.h new file mode 100644 index 0000000..8304440 --- /dev/null +++ b/Display/CGroupDlg.h @@ -0,0 +1,42 @@ +#ifndef CGROUPDLG_H +#define CGROUPDLG_H + +#include +#include "Model/CGroupItem.h" +#include "Model/CProfileManager.h" +#include "ui_groupDialog.h" + +class CGroupDlg : public QDialog, private Ui::groupDialog +{ + Q_OBJECT + +public: + CGroupDlg(QWidget* parent = 0); + CGroupDlg(const QString& groupName, const CGroupItem& groupItem, QWidget* parent = 0); + + virtual ~CGroupDlg() {} + +private slots: + void on_addProfileToolBn_clicked(); + void on_removeProfileToolBn_clicked(); + + void on_okButton_clicked(); + void on_cancelButton_clicked(); + void on_applyButton_clicked(); + + void on_groupComboBox_activated(const QString& comboText); + + void groupContentChanged(); + +private: + + void createActions(); + + void loadAllProfileListView(); + void loadGroupProfileListView(const QString& groupName); + + QString currentGroupName_; +}; +#endif // CGROUPDLG_H + + diff --git a/Display/CGroupListWidget.cpp b/Display/CGroupListWidget.cpp new file mode 100644 index 0000000..7af39ca --- /dev/null +++ b/Display/CGroupListWidget.cpp @@ -0,0 +1,86 @@ +#include "CGroupListWidget.h" + +CGroupListWidget::CGroupListWidget(QWidget *parent) +: QTreeView(parent) +{ + QFont currentFont = static_cast (this)->font(); + groupFontSize_ = currentFont.pointSize(); +} + +void CGroupListWidget::updateGroupListWidget() +{ + resizeColumnToContents(0); + resizeColumnToContents(1); + resizeColumnToContents(2); + resizeColumnToContents(3); +} + +void CGroupListWidget::mouseDoubleClickEvent(QMouseEvent* event) +{ + emit groupItemTriggered(); + QTreeView::mouseDoubleClickEvent(event); +} + +void CGroupListWidget::keyPressEvent(QKeyEvent* event) +{ + if (event->key() == Qt::Key_Return) { + emit groupItemTriggered(); + } else if ((event->key() == Qt::Key_Equal) && (event->modifiers() == Qt::ControlModifier)) { + groupZoomIn(); + } else if ((event->key() == Qt::Key_Minus) && (event->modifiers() == Qt::ControlModifier)) { + groupZoomOut(); + } + + QTreeView::keyPressEvent(event); +} + +void CGroupListWidget::updateGroupFont(const QFont& outputFont) +{ + QFont currentFont = static_cast (this)->font(); + + if (currentFont != outputFont) { + static_cast (this)->setFont(outputFont); + + groupFontSize_ = outputFont.pointSize(); + updateGroupListWidget(); + } +} + +void CGroupListWidget::groupZoomIn() +{ + groupFontSize_++; + QFont fnt = static_cast (this)->font();; + fnt.setPointSize(groupFontSize_); + static_cast (this)->setFont(fnt); + + updateGroupListWidget(); +} + +void CGroupListWidget::groupZoomOut() +{ + if (groupFontSize_ > 1) { + groupFontSize_--; + QFont fnt = static_cast (this)->font(); + fnt.setPointSize(groupFontSize_); + static_cast (this)->setFont(fnt); + + updateGroupListWidget(); + } +} + +void CGroupListWidget::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + groupZoomIn(); + } else { + groupZoomOut(); + } + } + QTreeView::wheelEvent(e); +} + + + + diff --git a/Display/CGroupListWidget.h b/Display/CGroupListWidget.h new file mode 100644 index 0000000..3b6b21e --- /dev/null +++ b/Display/CGroupListWidget.h @@ -0,0 +1,32 @@ +#ifndef CGROUP_LIST_WIDGET_H +#define CGROUP_LIST_WIDGET_H + +#include +#include + +class CGroupListWidget : public QTreeView +{ + Q_OBJECT + +public: + CGroupListWidget(QWidget *parent = 0); + + void mouseDoubleClickEvent(QMouseEvent* event); + void keyPressEvent(QKeyEvent* event); + + void wheelEvent(QWheelEvent *e); + + void updateGroupFont(const QFont& profileFont); +signals: + void groupItemTriggered(); + +private: + long groupFontSize_; + + void updateGroupListWidget(); + + void groupZoomIn(); + void groupZoomOut(); +}; + +#endif // CGROUP_LIST_WIDGET_H diff --git a/Display/CMainWindow.cpp b/Display/CMainWindow.cpp new file mode 100644 index 0000000..889d51b --- /dev/null +++ b/Display/CMainWindow.cpp @@ -0,0 +1,1920 @@ +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include + +#include + +#ifdef Q_OS_WIN + #include +#endif + +#include "CMainWindow.h" +#include "CAboutDlg.h" +#include "CProfileDlg.h" +#include "CGroupDlg.h" +#include "CConfigDlg.h" + +#include "Model/CProfileListModel.h" +#include "Model/CGroupListModel.h" +#include "Model/COutputListModel.h" + +#include "Utils/CUtils.h" + +#include "Model/qTagger/CTagResultItem.h" + +CMainWindow::CMainWindow(QWidget* parent) +: QMainWindow(parent), +m_bTagBuildInProgress(false) +{ + bool bAutoHideMenu; + + setupUi(this); + + // setting for progress bar + m_progressBar.setTextVisible(false); + m_progressBar.setMaximumSize(100, 16); + m_progressBar.setRange(0, 100); + m_progressBar.setValue(0); + m_progressBar.hide(); + + // hiding menuBar if needed + m_confManager = CConfigManager::getInstance(); + bAutoHideMenu = m_confManager->getAppSettingValue("AutoHideMenu", false).toBool(); + if (bAutoHideMenu) { + menuBar()->hide(); + } + + // add progressbar for status bar + statusBar()->addPermanentWidget(&m_progressBar, 1); + + // setting for timeline + m_timeLine.setDuration(200); + m_timeLine.setFrameRange(0, 100); + + // defining shortcut + + // filter under profile tab + profilePatternLineEditShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_P), this); + // filter under group tab + groupPatternLineEditShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_G), this); + + fileSearchShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), this); + tagSearchShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_S), this); + + outputExploreShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_E), this); + outputConsoleShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_M), this); + + profileLoadShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this); + profileUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_U), this); + + symbolSearchFrameShortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_F), this); + symbolSearchFrameShortcut->setContext(Qt::ApplicationShortcut); + + nextSymbolSearchShortcut = new QShortcut(QKeySequence::FindNext, this); + nextSymbolSearchShortcut->setContext(Qt::ApplicationShortcut); + + previousSymbolSearchShortcut = new QShortcut(QKeySequence::FindPrevious, this); + previousSymbolSearchShortcut->setContext(Qt::ApplicationShortcut); + +#ifdef Q_OS_WIN + previousSymbolSearchShortcut_win = new QShortcut(QKeySequence(Qt::Key_F4), this); + previousSymbolSearchShortcut_win->setContext(Qt::ApplicationShortcut); +#endif + + // shortcut in application context + profilePatternLineEditShortcut->setContext(Qt::ApplicationShortcut); + groupPatternLineEditShortcut->setContext(Qt::ApplicationShortcut); + + fileSearchShortcut->setContext(Qt::ApplicationShortcut); + tagSearchShortcut->setContext(Qt::ApplicationShortcut); + + outputExploreShortcut->setContext(Qt::ApplicationShortcut); + outputConsoleShortcut->setContext(Qt::ApplicationShortcut); + + profileLoadShortcut->setContext(Qt::ApplicationShortcut); + profileUpdateShortcut->setContext(Qt::ApplicationShortcut); + + // profile_listView, m_profileListModel + m_profileListModel = new CProfileListModel(this); + + m_profileListProxyModel = new QSortFilterProxyModel; + m_profileListProxyModel->setSourceModel(static_cast (m_profileListModel)); + m_profileListProxyModel->setDynamicSortFilter(true); + + m_profileListSelectionModel = new QItemSelectionModel(m_profileListProxyModel); + + profile_listView->setRootIsDecorated(false); + profile_listView->setModel(m_profileListProxyModel); + + profile_listView->setSelectionModel(m_profileListSelectionModel); + profile_listView->setSortingEnabled(true); + + profile_listView->setDragEnabled(false); + profile_listView->setAcceptDrops(true); + profile_listView->setDropIndicatorShown(true); + updateProfileListWidget(); + + // group_listView, m_groupListModel + m_groupListModel = new CGroupListModel(this); + + m_groupListProxyModel = new QSortFilterProxyModel; + m_groupListProxyModel->setSourceModel(static_cast (m_groupListModel)); + m_groupListProxyModel->setDynamicSortFilter(true); + + m_groupListSelectionModel = new QItemSelectionModel(m_groupListProxyModel); + + group_listView->setRootIsDecorated(false); + group_listView->setModel(m_groupListProxyModel); + + group_listView->setSelectionModel(m_groupListSelectionModel); + group_listView->setSortingEnabled(true); + + group_listView->setDragEnabled(false); + group_listView->setAcceptDrops(true); + group_listView->setDropIndicatorShown(true); + updateGroupListWidget(); + + // output_listView, m_outputListModel + m_outputListModel = new COutputListModel(this); + + output_listView->setOutputListModel(m_outputListModel); + + output_listView->setRootIsDecorated(false); + output_listView->setModel(m_outputListModel->getProxyModel()); + + output_listView->setSelectionModel(m_outputListModel->getSelectionModel()); + output_listView->setSortingEnabled(true); + + output_listView->setDragEnabled(true); + output_listView->setAcceptDrops(false); + + // view + bool bAlwaysOnTop; + bool bTransparent; + + bool bViewToolbar; + bool bViewProfilePanel; + bool bViewFilePanel; + + bAlwaysOnTop = m_confManager->getAppSettingValue("AlwaysOnTop", false).toBool(); + if (bAlwaysOnTop) { + setAlwaysOnTop(true); + actionAlways_on_top->setChecked(true); + } + + bTransparent = m_confManager->getAppSettingValue("Transparency", false).toBool(); + if (bTransparent) { + setTransparency(true); + actionTransparent->setChecked(true); + } + + bViewToolbar = m_confManager->getAppSettingValue("ViewToolbar", true).toBool(); + if (!bViewToolbar) { + toolBar->hide(); + actionToolbar->setChecked(false); + } else { + toolBar->show(); + actionToolbar->setChecked(true); + } + + bViewProfilePanel = m_confManager->getAppSettingValue("ViewProfilePanel", true).toBool(); + if (!bViewProfilePanel) { + mainTabWidget->hide(); + actionProfile_Panel->setChecked(false); + } else { + mainTabWidget->show(); + actionProfile_Panel->setChecked(true); + } + + bViewFilePanel = m_confManager->getAppSettingValue("ViewFilePanel", true).toBool(); + if (!bViewFilePanel) { + infoTabWidget->hide(); + actionFile_Panel->setChecked(false); + } else { + infoTabWidget->show(); + actionFile_Panel->setChecked(true); + } + + searchFrame->hide(); + + bool bProfileAndGroupFilterCaseSensitive; + bool bFileFilterCaseSensitive; + bool bSymbolSearchCaseSensitive; + + + bProfileAndGroupFilterCaseSensitive = m_confManager->getAppSettingValue("ProfileAndGroupFilterCaseSensitive", false).toBool(); + if (bProfileAndGroupFilterCaseSensitive) { + actionProfileAndGroupCaseSensitive->setChecked(true); + } else { + actionProfileAndGroupCaseSensitive->setChecked(false); + } + + bFileFilterCaseSensitive = m_confManager->getAppSettingValue("FileFilterCaseSensitive", false).toBool(); + if (bFileFilterCaseSensitive) { + actionFileCaseSensitive->setChecked(true); + } else { + actionFileCaseSensitive->setChecked(false); + } + + QString profileFontSettingStr; + QFont profileFont; + + profileFontSettingStr = m_confManager->getAppSettingValue("ProfileFont").toString(); + profileFont.fromString(profileFontSettingStr); + + if (profileFontSettingStr != "") { + profile_listView->updateProfileFont(profileFont); + output_listView->updateOutputFont(profileFont); // update output font as well + group_listView->updateGroupFont(profileFont); // update group font as well + } else { + profile_listView->updateProfileFont(QApplication::font()); // using system font by default + output_listView->updateOutputFont(QApplication::font()); + group_listView->updateGroupFont(QApplication::font()); + } + + + bSymbolSearchCaseSensitive = m_confManager->getAppSettingValue("SymbolSearchCaseSensitive", false).toBool(); + if (bSymbolSearchCaseSensitive) { + actionSymbolCaseSensitive->setChecked(true); + } else { + actionSymbolCaseSensitive->setChecked(false); + } + + textLayout_ = new QPlainTextDocumentLayout(&textDocument_); + textDocument_.setDocumentLayout(textLayout_); + textDocument_.setDefaultStyleSheet("a {color: #0066FF; font-weight: bold; font-family: Consolas; text-decoration: none} functionsig {color: #33F000; font-weight:bold; font-family: Consolas;} code { background: #FAFAFA; display: table-row; font-family: Consolas; white-space: nowrap} linenum {color: #9999CC; font-family: Consolas} keyword {color: #00CCCC; font-weight:bold} spacesize {font-size: 6pt} body {background: #FAFAFA; font-size: 16pt}"); + + createActions(); +} + +void CMainWindow::setSplitterSizes(const QList& splitterSizeList) +{ + splitter->setSizes(splitterSizeList); +} + +void CMainWindow::restoreTabWidgetPos() +{ + // tab widget + int profileTabIndex = m_confManager->getValue("Window", "profileTabIndex", 0).toInt(); + int fileTabIndex = m_confManager->getValue("Window", "fileTabIndex", 0).toInt(); + + // group instead of profile tab first + if (profileTabIndex == 1) { + mainTabWidget->clear(); + + // from ui_mainWindow.h + QIcon icon15; + icon15.addFile(QString::fromUtf8(":/Icons/22x22/document-open-6.png"), QSize(), QIcon::Normal, QIcon::Off); + mainTabWidget->addTab(groupTab, icon15, QString()); + + QIcon icon14; + icon14.addFile(QString::fromUtf8(":/Icons/22x22/view-process-all.png"), QSize(), QIcon::Normal, QIcon::Off); + mainTabWidget->addTab(profileTab, icon14, QString()); + + mainTabWidget->setTabText(mainTabWidget->indexOf(profileTab), QCoreApplication::translate("mainWindow", "Profile", 0, 0)); + mainTabWidget->setTabText(mainTabWidget->indexOf(groupTab), QCoreApplication::translate("mainWindow", "Group", 0, 0)); + } + + // symbol instead of file tab first + if (fileTabIndex == 1) { + infoTabWidget->clear(); + + QIcon icon17; + icon17.addFile(QString::fromUtf8(":/Icons/22x22/code-class.png"), QSize(), QIcon::Normal, QIcon::Off); + infoTabWidget->addTab(symbolTab, icon17, QString()); + + QIcon icon16; + icon16.addFile(QString::fromUtf8(":/Icons/22x22/document-new-4.png"), QSize(), QIcon::Normal, QIcon::Off); + infoTabWidget->addTab(fileTab, icon16, QString()); + + infoTabWidget->setTabText(infoTabWidget->indexOf(fileTab), QCoreApplication::translate("mainWindow", "File", 0, 0)); + infoTabWidget->setTabText(infoTabWidget->indexOf(symbolTab), QCoreApplication::translate("mainWindow", "Symbol", 0, 0)); + } +} + +void CMainWindow::updateProfileListWidget() +{ + profile_listView->resizeColumnToContents(0); + profile_listView->resizeColumnToContents(1); + profile_listView->resizeColumnToContents(2); + profile_listView->resizeColumnToContents(3); +} + +void CMainWindow::updateGroupListWidget() +{ + group_listView->resizeColumnToContents(0); + group_listView->resizeColumnToContents(1); + group_listView->resizeColumnToContents(2); + group_listView->resizeColumnToContents(3); +} + + +void CMainWindow::updateOutputListWidget() +{ + output_listView->resizeColumnToContents(0); + output_listView->resizeColumnToContents(1); + output_listView->resizeColumnToContents(2); +} + + +void CMainWindow::loadProfileList() +{ + QStringList profileList; + + m_profileListModel->clear(); // header data will also be clear + m_profileListModel->setColumnCount(4); // need to set back column count when QStandardItemModel clear otherwise setData will return false + + m_profileListModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + m_profileListModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Tag Update Datatime")); + m_profileListModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Profile Create Datetime")); + m_profileListModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Labels")); + + QMap profileMap; + + CProfileManager::getInstance()->getProfileMap(profileMap); + + foreach (const CProfileItem& profileItem, profileMap) { + m_profileListModel->addProfileItem(profileItem); + } + + updateProfileListWidget(); +} + +void CMainWindow::loadGroupList() +{ + QStringList groupList; + CGroupItem groupItem; + + m_groupListModel->clear(); // header data will also be clear + m_groupListModel->setColumnCount(4); // need to set back column count when QStandardItemModel clear otherwise setData will return false + + m_groupListModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + m_groupListModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Tag Update Datatime")); + m_groupListModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Group Create Datetime")); + m_groupListModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Labels")); + + QMap groupMap; + CProfileManager::getInstance()->getGroupMap(groupMap); + + foreach (const CGroupItem& groupItem, groupMap) { + m_groupListModel->addGroupItem(groupItem); + } + + updateGroupListWidget(); +} + + +void CMainWindow::loadOutputList() +{ + COutputItem outputItem; + + m_outputListModel->clearAndResetModel(); + + foreach (const COutputItem& outputItem, m_outputItemList) { + m_outputListModel->addItem(outputItem); + } + updateOutputListWidget(); +} + +void CMainWindow::createActions() +{ + connect(actionAbout, SIGNAL(triggered()), this, SLOT(on_aboutButton_clicked())); + + // [Profile action] + connect(actionProfileNew, SIGNAL(triggered()), this, SLOT(on_newProfileButton_clicked())); + + connect(actionProfileLoad, SIGNAL(triggered()), this, SLOT(on_loadProfileButton_clicked())); + + // default double click, enter action for profile list item + connect(profile_listView, SIGNAL(profileItemTriggered()), this, SLOT(on_loadProfileButton_clicked())); + + connect(actionProfileUpdate, SIGNAL(triggered()), this, SLOT(on_updateProfileButton_clicked())); + connect(actionProfileRebuildTag, SIGNAL(triggered()), this, SLOT(on_rebuildTagProfileButton_clicked())); + + connect(actionProfileModify, SIGNAL(triggered()), this, SLOT(on_editProfileButton_clicked())); + + connect(actionProfileDelete, SIGNAL(triggered()), this, SLOT(on_deleteProfileButton_clicked())); + + connect(actionProfileExplore, SIGNAL(triggered()), this, SLOT(on_exploreProfileButton_clicked())); + connect(actionProfileConsole, SIGNAL(triggered()), this, SLOT(on_consoleProfileButton_clicked())); + + connect(actionProfileGroup, SIGNAL(triggered()), this, SLOT(on_newGroupButton_clicked())); + + // [Group action] + connect(actionGroupNew, SIGNAL(triggered()), this, SLOT(on_newGroupButton_clicked())); + + connect(actionGroupLoad, SIGNAL(triggered()), this, SLOT(on_loadGroupButton_clicked())); + + // default double click, enter action for group list item + connect(group_listView, SIGNAL(groupItemTriggered()), this, SLOT(on_loadGroupButton_clicked())); + + connect(actionGroupUpdate, SIGNAL(triggered()), this, SLOT(on_updateGroupButton_clicked())); + connect(actionGroupModify, SIGNAL(triggered()), this, SLOT(on_editGroupButton_clicked())); + + connect(actionGroupDelete, SIGNAL(triggered()), this, SLOT(on_deleteGroupButton_clicked())); + + // [File action] + connect(actionOutputEdit, SIGNAL(triggered()), this, SLOT(on_outputEditPressed())); + + // default double click, enter action for output list item + connect(output_listView, SIGNAL(outputItemTriggered()), this, SLOT(on_outputEditPressed())); + + connect(actionOutputCopy, SIGNAL(triggered()), this, SLOT(on_outputCopyPressed())); + connect(actionOutputExplore, SIGNAL(triggered()), this, SLOT(on_outputExplorePressed())); + connect(actionOutputConsole, SIGNAL(triggered()), this, SLOT(on_outputConsolePressed())); + connect(actionOutputProperties, SIGNAL(triggered()), this, SLOT(on_outputPropertiesPressed())); + + connect(actionSearch, SIGNAL(triggered()), this, SLOT(on_searchButton_clicked())); + + connect(actionNextSymbolSearch, SIGNAL(triggered()), this, SLOT(on_nextSymbolButton_clicked())); + connect(actionPreviousSymbolSearch, SIGNAL(triggered()), this, SLOT(on_previousSymbolButton_clicked())); + + //connect(search_lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(on_searchButton_clicked())); + + connect(CProfileManager::getInstance(), SIGNAL(profileMapUpdated()), this, SLOT(loadProfileList())); + connect(CProfileManager::getInstance(), SIGNAL(groupMapUpdated()), this, SLOT(loadGroupList())); + + connect(&m_timeLine, SIGNAL(frameChanged(int)), &m_progressBar, SLOT(setValue(int))); + connect(&m_profileUpdateThread, SIGNAL(percentageCompleted(int)), this, SLOT(updateTagBuildProgress(int))); + + // update progress bar for cancelled tag build + connect(&m_profileUpdateThread, SIGNAL(cancelledTagBuild()), this, SLOT(updateCancelledTagBuild())); + // error occurs during run command + connect(&m_profileUpdateThread, SIGNAL(errorDuringRun(const QString&)), this, SLOT(on_errorDuringRun(const QString&))); + + connect(&m_profileLoadThread, SIGNAL(profileLoadPercentageCompleted(int)), this, SLOT(updateProfileLoadProgress(int))); + + connect(&m_groupLoadThread, SIGNAL(groupLoadPercentageCompleted(int)), this, SLOT(updateGroupLoadProgress(int))); + + // connecting shortcut action + connect(profilePatternLineEditShortcut, SIGNAL(activated()), this, SLOT(on_profilePatternLineEditShortcutPressed())); + connect(groupPatternLineEditShortcut, SIGNAL(activated()), this, SLOT(on_groupPatternLineEditShortcutPressed())); + + connect(fileSearchShortcut, SIGNAL(activated()), this, SLOT(on_filePatternLineEditShortcutPressed())); + connect(tagSearchShortcut, SIGNAL(activated()), this, SLOT(on_searchLineEditShortcutPressed())); + + connect(outputExploreShortcut, SIGNAL(activated()), this, SLOT(on_outputExplorePressed())); + connect(outputConsoleShortcut, SIGNAL(activated()), this, SLOT(on_outputConsolePressed())); + + connect(profilePattern_lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(profileFilterRegExpChanged())); + connect(groupPattern_lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(groupFilterRegExpChanged())); + + connect(actionProfileAndGroupCaseSensitive, SIGNAL(toggled(bool)), + this, SLOT(profileFilterRegExpChanged())); + + connect(actionProfileAndGroupCaseSensitive, SIGNAL(toggled(bool)), + this, SLOT(groupFilterRegExpChanged())); + + // for cancel update tag + connect(actionCancelTagUpdate, SIGNAL(triggered()), this, SLOT(on_cancelTagUpdate())); + // for info tab widget tool button + + connect(filePattern_lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(fileFilterRegExpChanged())); + connect(actionFileCaseSensitive, SIGNAL(toggled(bool)), + this, SLOT(fileFilterRegExpChanged())); + connect(actionSymbolCaseSensitive, SIGNAL(toggled(bool)), + this, SLOT(searchLineEditChanged())); + + connect(search_lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(searchLineEditChanged())); + + connect(&m_completer, SIGNAL(activated(const QString &)), + this, SLOT(queryTag(const QString&))); + + // symbol search frame + connect(symbolSearchFrameShortcut, SIGNAL(activated()), this, SLOT(on_symbolSearchFrameShortcutPressed())); + connect(frameSymbol_lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(frameSymbolLineEditChanged())); + + connect(nextSymbolSearchShortcut, SIGNAL(activated()), this, SLOT(on_nextSymbolButton_clicked())); + connect(previousSymbolSearchShortcut, SIGNAL(activated()), this, SLOT(on_previousSymbolButton_clicked())); + +#ifdef Q_OS_WIN + connect(previousSymbolSearchShortcut_win, SIGNAL(activated()), this, SLOT(on_previousSymbolButton_clicked())); +#endif + + // zoom in, zoom out + actionWebZoomIn->setShortcut(QKeySequence::ZoomIn); + actionWebZoomOut->setShortcut(QKeySequence::ZoomOut); + +#ifdef ENABLE_SYMBOL_WEB_VIEW + webView->addAction(actionWebZoomIn); + webView->addAction(actionWebZoomOut); +#elif defined ENABLE_SYMBOL_RICH_TEXT_VIEW + + /* + symbol_textBrowser->setContextMenuPolicy(Qt::NoContextMenu); + symbol_textBrowser->setReadOnly(true); + symbol_textBrowser->setUndoRedoEnabled(false); + */ + + symbol_textBrowser->addAction(actionWebZoomIn); + symbol_textBrowser->addAction(actionWebZoomOut); +#else + symbol_textBrowser->setReadOnly(true); + symbol_textBrowser->setLineWrapMode(QPlainTextEdit::NoWrap); + + QTextCharFormat charFormat; + charFormat.setFontFamily("Consolas"); + charFormat.setFontPointSize(7); + + symbol_textBrowser->setCurrentCharFormat(charFormat); +#endif + + + connect(actionWebZoomIn, SIGNAL(triggered()), this, SLOT(webZoomIn())); + connect(actionWebZoomOut, SIGNAL(triggered()), this, SLOT(webZoomOut())); +} + +void CMainWindow::on_newProfileButton_clicked() +{ + QDialog* dialog = new CProfileDlg(); + dialog->exec(); +} + +// load the profile into environment +void CMainWindow::on_loadProfileButton_clicked() +{ + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + QString profileItemName; + CProfileItem profileItem; + + if (profileSelected != 0) { + if (profileSelected > 1) { + QMessageBox::information(this, "Load", "Only one profile can be loaded each time", QMessageBox::Ok); + } else { + + profileItemName = profileItemNameList.at(0); + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + m_currentProfileItem = profileItem; + + QDir currentDir(QDir::currentPath()); + + // only load profile if source directory exists + if (currentDir.exists(profileItem.m_srcDir)) { + statusBar()->showMessage("Loading profile " + profileItem.m_name + "..."); + + filePattern_lineEdit->clear(); + + m_profileLoadThread.setCurrentProfileItem(profileItem); + m_profileLoadThread.setTaggerPtr(&m_tagger); + m_profileLoadThread.setOutputItemListPtr(&m_outputItemList); + + m_profileLoadThread.start(); + + } else { + QMessageBox::warning(this, "Load", "Cannot load profile. Source directory doesn't exists.", QMessageBox::Ok); + } + } + } +} + +// update tags for the profile +void CMainWindow::on_updateProfileButton_clicked() +{ + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + QString profileItemName; + CProfileItem profileItem; + QDateTime currDateTime; + + if (profileSelected != 0) { + if (profileSelected > 1) { + QMessageBox::information(this, "Update", "Only one profile can be updated each time", QMessageBox::Ok); + } else { + profileItemName = profileItemNameList.at(0); + + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + QDir currentDir(QDir::currentPath()); + + // only update profile if source directory exists + if (currentDir.exists(profileItem.m_srcDir)) { + currDateTime = QDateTime::currentDateTime(); + profileItem.m_tagUpdateDateTime = currDateTime.toString("dd/MM/yyyy hh:mm:ss"); + + // tag last update date time updated so need update in profile manager + CProfileManager::getInstance()->updateProfileItem(profileItemName, profileItem); + + statusBar()->showMessage("Updating tag for " + profileItem.m_name + "..."); + + m_profileUpdateThread.setRebuildTag(false); + m_profileUpdateThread.setCurrentProfileItem(profileItem); + m_profileUpdateThread.start(QThread::HighestPriority); // priority for update thread + } else { + QMessageBox::warning(this, "Load", "Cannot update profile. Source directory doesn't exists.", QMessageBox::Ok); + } + } + } +} + +void CMainWindow::on_rebuildTagProfileButton_clicked() +{ + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + QString profileItemName; + CProfileItem profileItem; + QDateTime currDateTime; + + if (profileSelected != 0) { + if (profileSelected > 1) { + QMessageBox::information(this, "Rebuild", "Only one profile can be rebuilt each time", QMessageBox::Ok); + } else { + profileItemName = profileItemNameList.at(0); + + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + QDir currentDir(QDir::currentPath()); + + // only update profile if source directory exists + if (currentDir.exists(profileItem.m_srcDir)) { + currDateTime = QDateTime::currentDateTime(); + profileItem.m_tagUpdateDateTime = currDateTime.toString("dd/MM/yyyy hh:mm:ss"); + + // tag last update date time updated so need update in profile manager + CProfileManager::getInstance()->updateProfileItem(profileItemName, profileItem); + + statusBar()->showMessage("Rebuilding tag for " + profileItem.m_name + "..."); + + m_profileUpdateThread.setRebuildTag(true); + m_profileUpdateThread.setCurrentProfileItem(profileItem); + m_profileUpdateThread.start(QThread::HighestPriority); // priority for update thread + } else { + QMessageBox::warning(this, "Load", "Cannot rebuilt profile. Source directory doesn't exists.", QMessageBox::Ok); + } + } + } +} + + +// get the profile name of the selected list item +QStringList CMainWindow::getSelectedProfileItemNameList() +{ + QModelIndexList indexSelectedList; + QModelIndex mappedIndex; + int rowSelected; + QStandardItem* itemSelected; + + QString profileItemName; + QStringList profileItemNameList; + + // get selected items index list + indexSelectedList = m_profileListSelectionModel->selectedIndexes(); + + foreach (const QModelIndex& indexSelected, indexSelectedList) { + // map back from proxy model + mappedIndex = m_profileListProxyModel->mapToSource(indexSelected); + rowSelected = mappedIndex.row(); + + if (indexSelected.isValid()) { + itemSelected = m_profileListModel->item(rowSelected, 0); + if (itemSelected != 0) { + profileItemName = itemSelected->text(); + } + } + + // as all items in the same row with differnt columns will also be returned in selectedIndexes + if (!profileItemNameList.contains(profileItemName)) { + // not add profile name to the list if already added + profileItemNameList += profileItemName; + } + } + + return profileItemNameList; +} + +// get the group name of the selected list item +QStringList CMainWindow::getSelectedGroupItemNameList() +{ + QModelIndexList indexSelectedList; + QModelIndex mappedIndex; + int rowSelected; + QStandardItem* itemSelected; + + QString groupItemName; + QStringList groupItemNameList; + + // get selected items index list + indexSelectedList = m_groupListSelectionModel->selectedIndexes(); + + foreach (const QModelIndex& indexSelected, indexSelectedList) { + // map back from proxy model + mappedIndex = m_groupListProxyModel->mapToSource(indexSelected); + rowSelected = mappedIndex.row(); + + if (indexSelected.isValid()) { + itemSelected = m_groupListModel->item(rowSelected, 0); + if (itemSelected != 0) { + groupItemName = itemSelected->text(); + } + } + + // as all items in the same row with differnt columns will also be returned in selectedIndexes + if (!groupItemNameList.contains(groupItemName)) { + // not add group name to the list if already added + groupItemNameList += groupItemName; + } + } + + return groupItemNameList; +} + +// get the profile name of the selected list item +QStringList CMainWindow::getSelectedOutputItemNameList() +{ + QModelIndexList indexSelectedList; + QModelIndex mappedIndex; + int rowSelected; + QStandardItem* itemSelected; + + QString outputItemName; + QStringList outputItemNameList; + + // get selected items index list + indexSelectedList = m_outputListModel->getSelectionModel()->selectedIndexes(); + + foreach (const QModelIndex& indexSelected, indexSelectedList) { + // map back from proxy model + mappedIndex = m_outputListModel->getProxyModel()->mapToSource(indexSelected); + rowSelected = mappedIndex.row(); + + if (indexSelected.isValid()) { + itemSelected = m_outputListModel->item(rowSelected, 0); + if (itemSelected != 0) { + outputItemName = itemSelected->text(); + } + } + + // as all items in the same row with differnt columns will also be returned in selectedIndexes + if (!outputItemNameList.contains(outputItemName)) { + // not add profile name to the list if already added + outputItemNameList += outputItemName; + } + } + + return outputItemNameList; +} + +// edit selected profile +void CMainWindow::on_editProfileButton_clicked() +{ + CProfileItem profileItem; + + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + QString profileItemName; + + if (profileSelected != 0) { // only do processing when a item is selected + if (profileSelected > 1) { + QMessageBox::information(this, "Edit", "Only one profile can be edited each time", QMessageBox::Ok); + } else { + + profileItemName = profileItemNameList.at(0); + + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + QDialog* dialog = new CProfileDlg(profileItemName, profileItem); + + dialog->exec(); + } + } +} + +// delete selected profile +void CMainWindow::on_deleteProfileButton_clicked() +{ + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + int ret; + + if (profileSelected != 0) { // only do processing when a item is selected + if (profileSelected > 1) { + ret = QMessageBox::question(this, "Confirm multiple delete", "Delete " + QString::number(profileSelected) + " selected profiles?", QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::Yes) { + + foreach (const QString& profileItemName, profileItemNameList) { + CProfileManager::getInstance()->removeProfileItem(profileItemName); + } + } + } else { + QString profileItemName = profileItemNameList.at(0); + ret = QMessageBox::question(this, "Confirm delete", "Delete the selected profile?", QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::Yes) { + CProfileManager::getInstance()->removeProfileItem(profileItemName); + } + } + } +} + +void CMainWindow::on_exploreProfileButton_clicked() +{ + CProfileItem profileItem; + + QStringList selectedItemList = getSelectedProfileItemNameList(); + int itemSelected = selectedItemList.size(); + + QString profileItemName; + + QString executeDir; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Explore", "Can only explore one path", QMessageBox::Ok); + } else { + profileItemName = selectedItemList.at(0); + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + executeDir = profileItem.m_srcDir; + +#ifdef Q_OS_WIN + QString excuteMethod = "explore"; + ShellExecute(NULL, reinterpret_cast(excuteMethod.utf16()), reinterpret_cast(executeDir.utf16()), NULL, NULL, SW_NORMAL); +#else + QDesktopServices::openUrl(QUrl(executeDir, QUrl::TolerantMode)); +#endif + } + } +} + +void CMainWindow::on_consoleProfileButton_clicked() +{ + CProfileItem profileItem; + + QStringList selectedItemList = getSelectedProfileItemNameList(); + int itemSelected = selectedItemList.size(); + + QString profileItemName; + + QString executeDir; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Console", "Can only open console from one path", QMessageBox::Ok); + } else { + profileItemName = selectedItemList.at(0); + profileItem = CProfileManager::getInstance()->getProfileItem(profileItemName); + + executeDir = profileItem.m_srcDir; + +#ifdef Q_OS_WIN + QString excuteMethod = "open"; + QString consoleCommnad = "cmd.exe"; + + ShellExecute(NULL, reinterpret_cast(excuteMethod.utf16()), reinterpret_cast(consoleCommnad.utf16()), NULL, reinterpret_cast(executeDir.utf16()), SW_NORMAL); +#else + // not implemented +#endif + } + } +} + +void CMainWindow::on_newGroupButton_clicked() +{ + QDialog* dialog = new CGroupDlg(); + dialog->exec(); +} + +void CMainWindow::on_loadGroupButton_clicked() +{ + QStringList groupItemNameList = getSelectedGroupItemNameList(); + int groupSelected = groupItemNameList.size(); + + QString groupItemName; + CGroupItem groupItem; + + if (groupSelected != 0) { + if (groupSelected > 1) { + QMessageBox::information(this, "Load", "Only one group can be loaded each time", QMessageBox::Ok); + } else { + + groupItemName = groupItemNameList.at(0); + groupItem = CProfileManager::getInstance()->getGroupItem(groupItemName); + + m_currentGroupItem = groupItem; + + QDir currentDir(QDir::currentPath()); + + // only load group if source directory exists +// if (currentDir.exists(groupItem.m_srcDir)) { + statusBar()->showMessage("Loading group " + groupItem.m_name + "..."); + + filePattern_lineEdit->clear(); + + m_groupLoadThread.setCurrentGroupItem(groupItem); + m_groupLoadThread.setTaggerPtr(&m_tagger); + m_groupLoadThread.setOutputItemListPtr(&m_outputItemList); + + m_groupLoadThread.start(); + +/* + } else { + QMessageBox::warning(this, "Load", "Cannot load group. Source directory doesn't exists.", QMessageBox::Ok); + } +*/ + } + } +} + +void CMainWindow::on_updateGroupButton_clicked() +{ + +} + +void CMainWindow::on_editGroupButton_clicked() +{ + CGroupItem groupItem; + + QStringList groupItemNameList = getSelectedGroupItemNameList(); + int groupSelected = groupItemNameList.size(); + + QString groupItemName; + + if (groupSelected != 0) { // only do processing when a item is selected + if (groupSelected > 1) { + QMessageBox::information(this, "Edit", "Only one group can be edited each time", QMessageBox::Ok); + } else { + + groupItemName = groupItemNameList.at(0); + + groupItem = CProfileManager::getInstance()->getGroupItem(groupItemName); + + QDialog* dialog = new CGroupDlg(groupItemName, groupItem); + + dialog->exec(); + } + } +} + +void CMainWindow::on_deleteGroupButton_clicked() +{ + QStringList groupItemNameList = getSelectedGroupItemNameList(); + int groupSelected = groupItemNameList.size(); + + int ret; + + if (groupSelected != 0) { // only do processing when a item is selected + + if (groupSelected > 1) { + ret = QMessageBox::question(this, "Confirm multiple delete", "Delete " + QString::number(groupSelected) + " selected groups?", QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::Yes) { + + foreach (const QString& groupItemName, groupItemNameList) { + CProfileManager::getInstance()->removeGroupItem(groupItemName); + } + } + } else { + QString groupItemName = groupItemNameList.at(0); + ret = QMessageBox::question(this, "Confirm delete", "Delete the selected group?", QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::Yes) { + CProfileManager::getInstance()->removeGroupItem(groupItemName); + } + } + } +} + +void CMainWindow::on_aboutButton_clicked() +{ + QDialog* dialog = new CAboutDlg(); + dialog->exec(); +} + +void CMainWindow::on_clearOutputButton_clicked() +{ +// output_listView->clear(); +} + +void CMainWindow::on_clearLogButton_clicked() +{ + +} + +void CMainWindow::setAlwaysOnTop(bool enable) +{ + Qt::WindowFlags flags = windowFlags(); + + if (enable) { + flags |= Qt::WindowStaysOnTopHint; + } else { + flags ^= Qt::WindowStaysOnTopHint; + } + + QPoint p(frameGeometry().x(),frameGeometry().y()); // current position before set window flags + + setWindowFlags(flags); + + this->move(p); + this->show(); + + // save setting + m_confManager->setAppSettingValue("AlwaysOnTop", enable); +} + +void CMainWindow::on_actionAlways_on_top_toggled() +{ + if (actionAlways_on_top->isChecked()) { + setAlwaysOnTop(true); + } else { + setAlwaysOnTop(false); + } + on_actionTransparent_toggled(); // still transparency +} + +void CMainWindow::setTransparency(bool enable) +{ + if (enable) { + setWindowOpacity(0.7); + } else { + setWindowOpacity(1); + } + + // save setting + m_confManager->setAppSettingValue("Transparency", enable); +} + +void CMainWindow::on_actionTransparent_toggled() +{ + if (actionTransparent->isChecked()) { + setTransparency(true); + } else { + setTransparency(false); + } +} + +void CMainWindow::on_actionToolbar_toggled() +{ + if (actionToolbar->isChecked()) { + toolBar->show(); + m_confManager->setAppSettingValue("ViewToolbar", true); + } else { + toolBar->hide(); + m_confManager->setAppSettingValue("ViewToolbar", false); + } +} + +void CMainWindow::on_actionProfile_Panel_toggled() +{ + if (actionProfile_Panel->isChecked()) { + mainTabWidget->show(); + m_confManager->setAppSettingValue("ViewProfilePanel", true); + } else { + mainTabWidget->hide(); + m_confManager->setAppSettingValue("ViewProfilePanel", true); + } +} + +void CMainWindow::on_actionFile_Panel_toggled() +{ + if (actionFile_Panel->isChecked()) { + infoTabWidget->show(); + m_confManager->setAppSettingValue("ViewFilePanel", true); + } else { + infoTabWidget->hide(); + m_confManager->setAppSettingValue("ViewFilePanel", true); + } +} + +void CMainWindow::on_actionExit_triggered() +{ + this->close(); +} + +// configuration dialog +void CMainWindow::on_actionSetting_triggered() +{ + QDialog* dialog = new CConfigDlg(); + + int dialogCode = dialog->exec(); + + if (dialogCode == QDialog::Accepted) { + QFont updatedFont = static_cast (dialog)->getProfileDefaultFont(); + + profile_listView->updateProfileFont(updatedFont); + output_listView->updateOutputFont(updatedFont); + } +} + +void CMainWindow::saveWidgetPosition() +{ + QList splitterSizeList; + QString splitterSizeListStr = ""; + + m_confManager->setValue("Window", "geometry", saveGeometry()); + + splitterSizeList = splitter->sizes(); + foreach (const int& splitterSize, splitterSizeList) { + splitterSizeListStr += QString::number(splitterSize) + " "; + } + + m_confManager->setValue("Window", "splitter", splitterSizeListStr); + + int profileTabIndex = mainTabWidget->indexOf(profileTab); + int fileTabIndex = infoTabWidget->indexOf(fileTab); + + m_confManager->setValue("Window", "profileTabIndex", QString::number(profileTabIndex)); + m_confManager->setValue("Window", "fileTabIndex", QString::number(fileTabIndex)); + + m_confManager->updateConfig(); +} + +void CMainWindow::closeEvent(QCloseEvent *event) +{ + saveWidgetPosition(); + event->accept(); +} + +void CMainWindow::updateTagBuildProgress(int percentage) +{ + // show the progress bar when pecentage completed >= 0 + if (percentage >= 0) { + m_progressBar.show(); + m_bTagBuildInProgress = true; + } + + m_progressBar.setValue(percentage); + + // hide the progress bar when completed + if (percentage == 100) { + statusBar()->showMessage("Tag update completed."); + m_bTagBuildInProgress = false; + m_progressBar.hide(); + } +} + +void CMainWindow::updateProfileLoadProgress(int percentage) +{ + if (percentage == 100) { + loadOutputList(); + + search_lineEdit->clear(); // clear symbol search line edit + symbol_textBrowser->clear(); // clear symbol text widget as well + + statusBar()->showMessage("Profile " + m_currentProfileItem.m_name + " loaded."); + } else if (percentage == 0) { + statusBar()->showMessage("Failed to load Profile " + m_currentProfileItem.m_name + "."); + } +} + +void CMainWindow::updateGroupLoadProgress(int percentage) +{ + if (percentage == 100) { + loadOutputList(); + + statusBar()->showMessage("Group " + m_currentGroupItem.m_name + " loaded."); + } else if (percentage == 0) { + statusBar()->showMessage("Failed to load Group " + m_currentGroupItem.m_name + "."); + } +} + + +void CMainWindow::updateCancelledTagBuild() +{ + m_progressBar.reset(); + m_progressBar.setValue(0); + m_progressBar.hide(); + m_bTagBuildInProgress = false; + + statusBar()->showMessage("Tag update cancelled."); +} + +void CMainWindow::on_errorDuringRun(const QString& cmdStr) +{ + m_progressBar.reset(); + m_progressBar.setValue(0); + m_progressBar.hide(); + m_bTagBuildInProgress = false; + + appendLogList(TRACE_ERROR, cmdStr); + + QMessageBox::warning(this, "Tag update", "Error running command.\n" + "Please check log message for details.", QMessageBox::Ok); +} + +void CMainWindow::on_profilePatternLineEditShortcutPressed() +{ + const int profileTabIndex = mainTabWidget->indexOf(profileTab); + + mainTabWidget->setCurrentIndex(profileTabIndex); + profilePattern_lineEdit->setFocus(); +} + +void CMainWindow::on_groupPatternLineEditShortcutPressed() +{ + const int groupTabIndex = mainTabWidget->indexOf(groupTab); + + mainTabWidget->setCurrentIndex(groupTabIndex); + groupPattern_lineEdit->setFocus(); +} + +void CMainWindow::on_filePatternLineEditShortcutPressed() +{ + const int fileTabIndex = infoTabWidget->indexOf(fileTab); + + infoTabWidget->setCurrentIndex(fileTabIndex); + filePattern_lineEdit->setFocus(); +} + +void CMainWindow::on_searchLineEditShortcutPressed() +{ + const int symbolTabIndex = infoTabWidget->indexOf(symbolTab); + + infoTabWidget->setCurrentIndex(symbolTabIndex); + search_lineEdit->setFocus(); +} + +void CMainWindow::on_infoTabWidgetToolBn_clicked() +{ + if (infoTabWidget->isHidden()) { + infoTabWidget->show(); + } else { + m_priorMainTabWidgetSize = infoTabWidget->size(); + + infoTabWidget->hide(); + + /* + containerwidget->layout()->invalidate(); + QWidget *parent = containerwidget; + while (parent) { + parent->adjustSize(); + parent = parent->parentWidget(); + } + */ + } +} + +void CMainWindow::profileFilterRegExpChanged() +{ + Qt::CaseSensitivity caseSensitivity; + + if (actionProfileAndGroupCaseSensitive->isChecked()) { + caseSensitivity = Qt::CaseSensitive; + m_confManager->setAppSettingValue("actionProfileAndGroupCaseSensitive", true); + } else { + caseSensitivity = Qt::CaseInsensitive; + m_confManager->setAppSettingValue("actionProfileAndGroupCaseSensitive", false); + } + + QRegExp regExp(profilePattern_lineEdit->text(), caseSensitivity, QRegExp::RegExp); + + m_profileListProxyModel->setFilterRegExp(regExp); +} + +void CMainWindow::groupFilterRegExpChanged() +{ + Qt::CaseSensitivity caseSensitivity; + + if (actionProfileAndGroupCaseSensitive->isChecked()) { + caseSensitivity = Qt::CaseSensitive; + m_confManager->setAppSettingValue("actionProfileAndGroupCaseSensitive", true); + } else { + caseSensitivity = Qt::CaseInsensitive; + m_confManager->setAppSettingValue("actionProfileAndGroupCaseSensitive", false); + } + + QRegExp regExp(groupPattern_lineEdit->text(), caseSensitivity, QRegExp::RegExp); + + m_groupListProxyModel->setFilterRegExp(regExp); +} + +void CMainWindow::fileFilterRegExpChanged() +{ + Qt::CaseSensitivity caseSensitivity; + + if (actionFileCaseSensitive->isChecked()) { + caseSensitivity = Qt::CaseSensitive; + m_confManager->setAppSettingValue("FileFilterCaseSensitive", true); + } else { + caseSensitivity = Qt::CaseInsensitive; + m_confManager->setAppSettingValue("FileFilterCaseSensitive", false); + } + + QString trimmedFilePattern = filePattern_lineEdit->text().trimmed() ; + + QRegExp regExp(trimmedFilePattern, caseSensitivity, QRegExp::RegExp); + + m_outputListModel->getProxyModel()->setFilterRegExp(regExp); +} + +void CMainWindow::searchLineEditChanged() +{ + Qt::CaseSensitivity caseSensitivity; + + if (actionSymbolCaseSensitive->isChecked()) { + caseSensitivity = Qt::CaseSensitive; + m_confManager->setAppSettingValue("SymbolSearchCaseSensitive", true); + } else { + caseSensitivity = Qt::CaseInsensitive; + m_confManager->setAppSettingValue("SymbolSearchCaseSensitive", false); + } + + QStringList tagList; + m_tagger.getMatchedTags(search_lineEdit->text(), tagList, caseSensitivity); + + m_stringListModel.setStringList(tagList); + + m_completer.setModel(&m_stringListModel); + m_completer.setModelSorting(QCompleter::CaseSensitivelySortedModel); + m_completer.setCaseSensitivity(caseSensitivity); + + search_lineEdit->setCompleter(&m_completer); +} + +void CMainWindow::on_symbolSearchFrameShortcutPressed() +{ + const int symbolTabIndex = infoTabWidget->indexOf(symbolTab); + + if (infoTabWidget->currentIndex() == symbolTabIndex) { + if (searchFrame->isHidden()) { + searchFrame->show(); + frameSymbol_lineEdit->setFocus(); + } else { + searchFrame->hide(); + search_lineEdit->setFocus(); + } + } +} + +void CMainWindow::frameSymbolLineEditChanged() +{ +#ifdef ENABLE_SYMBOL_WEB_VIEW + webView->findText("", (QWebPage::FindFlags) QWebPage::HighlightAllOccurrences); + webView->findText(frameSymbol_lineEdit->text(), (QWebPage::FindFlags) QWebPage::HighlightAllOccurrences); +#elif defined ENABLE_SYMBOL_RICH_TEXT_VIEW + symbol_textBrowser->findText("", (QTextDocument::FindFlags) 0); + symbol_textBrowser->findText(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) 0); +#else + symbol_textBrowser->find("", (QTextDocument::FindFlags) 0); + symbol_textBrowser->find(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) 0); +#endif +} + +void CMainWindow::on_nextSymbolButton_clicked() +{ +#ifdef ENABLE_SYMBOL_WEB_VIEW + webView->findText(frameSymbol_lineEdit->text(), QWebPage::FindWrapsAroundDocument); +#elif defined ENABLE_SYMBOL_RICH_TEXT_VIEW + symbol_textBrowser->findText(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) 0); +#else + symbol_textBrowser->find(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) 0); +#endif +} + +void CMainWindow::on_previousSymbolButton_clicked() +{ +#ifdef ENABLE_SYMBOL_WEB_VIEW + webView->findText(frameSymbol_lineEdit->text(), QWebPage::FindBackward | QWebPage::FindWrapsAroundDocument); +#elif defined ENABLE_SYMBOL_RICH_TEXT_VIEW + symbol_textBrowser->findText(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) QTextDocument::FindBackward); +#else + symbol_textBrowser->find(frameSymbol_lineEdit->text(), (QTextDocument::FindFlags) QTextDocument::FindBackward); +#endif +} + + +void CMainWindow::on_cancelTagUpdate() +{ + int ret; + + ret = QMessageBox::question(this, "Tag update", "Cancel tag update?", QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::Yes) { + statusBar()->showMessage("Cancelling tag update..."); + m_profileUpdateThread.cancelUpdate(); + } +} + +// right click context menu +void CMainWindow::contextMenuEvent(QContextMenuEvent* event) +{ + QPoint p; + + // profile_listView area and have selected profile + p = profile_listView->mapFromGlobal(event->globalPos()); + + // get current active tab + const int mainTabIndex = mainTabWidget->currentIndex(); + const int profileTabIndex = mainTabWidget->indexOf(profileTab); + const int groupTabIndex = mainTabWidget->indexOf(groupTab); + + if (mainTabIndex == profileTabIndex) { + // in area of profile_listView + if (profile_listView->rect().contains(p)) { + QStringList profileItemNameList = getSelectedProfileItemNameList(); + int profileSelected = profileItemNameList.size(); + + if (profileSelected != 0) { // only show menu if have more than 1 selected profile + // only show delete menu if more than one profile selected + if (profileSelected > 1) { + QMenu menu(this); + menu.addAction(actionProfileDelete); + menu.addAction(actionProfileGroup); + + menu.exec(event->globalPos()); + } else { + QMenu menu(this); + + menu.addAction(actionProfileNew); + menu.addAction(actionProfileLoad); + menu.addAction(actionProfileRebuildTag); + menu.addAction(actionProfileModify); + menu.addAction(actionProfileDelete); + menu.addAction(actionProfileGroup); + + menu.addAction(actionProfileExplore); + +#ifdef Q_OS_WIN + menu.addAction(actionProfileConsole); + #endif + menu.exec(event->globalPos()); + } + } + } + } else if (mainTabIndex == groupTabIndex) { + // in area of group_listView + if (group_listView->rect().contains(p)) { + QStringList groupItemNameList = getSelectedGroupItemNameList(); + int groupSelected = groupItemNameList.size(); + + if (groupSelected != 0) { // only show menu if have more than 1 selected group + // only show delete menu if more than one group selected + if (groupSelected > 1) { + QMenu menu(this); + + menu.addAction(actionGroupDelete); + menu.exec(event->globalPos()); + } else { + QMenu menu(this); + + menu.addAction(actionGroupNew); + menu.addAction(actionGroupLoad); + menu.addAction(actionGroupUpdate); + menu.addAction(actionGroupModify); + menu.addAction(actionGroupDelete); + + menu.exec(event->globalPos()); + } + } + } + } + + + // get current active tab + const int infoTabIndex = infoTabWidget->currentIndex(); + + const int fileTabIndex = infoTabWidget->indexOf(fileTab); + + // in area of output_listView and correct tab page + p = output_listView->mapFromGlobal(event->globalPos()); + if ((output_listView->rect().contains(p)) && (infoTabIndex == fileTabIndex)) { + + QStringList outputItemNameList = getSelectedOutputItemNameList(); + int outputItemSelected = outputItemNameList.size(); + + if (outputItemSelected != 0) { // only show menu if have more than 1 selected profile + if (outputItemSelected > 1) { + QMenu menu(this); + + menu.addAction(actionOutputCopy); + menu.exec(event->globalPos()); + } else { + QMenu menu(this); + + menu.addAction(actionOutputEdit); + menu.addAction(actionOutputExplore); + + menu.addAction(actionOutputCopy); + menu.addAction(actionOutputConsole); + +#ifdef Q_OS_WIN + menu.addAction(actionOutputProperties); +#endif + menu.exec(event->globalPos()); + } + } + + } + + // in area of status bar + p = statusBar()->mapFromGlobal(event->globalPos()); + // only show cancel tag update menu when tag build in progress + if (statusBar()->rect().contains(p) && m_bTagBuildInProgress) { + QMenu menu(this); + + menu.addAction(actionCancelTagUpdate); + + menu.exec(event->globalPos()); + } + +} + +void CMainWindow::on_outputEditPressed() +{ + QStringList selectedItemList = getSelectedOutputItemNameList(); + int itemSelected = selectedItemList.size(); + + QString executeDir; + QString editFilename; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Edit", "Can only edit one file", QMessageBox::Ok); + } else { + QFileInfo fileInfo(selectedItemList.at(0)); + executeDir = fileInfo.absoluteDir().absolutePath(); + + QString consoleCommnad = m_confManager->getAppSettingValue("DefaultEditor").toString(); + +#ifdef Q_OS_WIN + editFilename = "\"" + selectedItemList.at(0) + "\""; +#else + editFilename = selectedItemList.at(0); +#endif + +#ifdef Q_OS_WIN + QString excuteMethod = "open"; + + ShellExecute(NULL, reinterpret_cast(excuteMethod.utf16()), reinterpret_cast(consoleCommnad.utf16()), reinterpret_cast (editFilename.utf16()), reinterpret_cast(executeDir.utf16()), SW_NORMAL); +#else + QProcess::startDetached(consoleCommnad, QStringList(editFilename)); +#endif + } + } +} + +void CMainWindow::on_outputCopyPressed() +{ + QStringList selectedItemList = getSelectedOutputItemNameList(); + QString clipBoardStr = ""; + + if (selectedItemList.size() > 0) { + foreach (const QString& selectedItem, selectedItemList) { + clipBoardStr = clipBoardStr + selectedItem + "\n"; + } + + QClipboard *clipboard = QApplication::clipboard(); + + clipboard->setText(clipBoardStr); + } +} + +void CMainWindow::on_outputExplorePressed() +{ + QStringList selectedItemList = getSelectedOutputItemNameList(); + int itemSelected = selectedItemList.size(); + + QString executeDir; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Explore", "Can only explore one path", QMessageBox::Ok); + } else { + QFileInfo fileInfo(selectedItemList.at(0)); + executeDir = fileInfo.absoluteDir().absolutePath(); + +#ifdef Q_OS_WIN + QString excuteMethod = "explore"; + ShellExecute(NULL, reinterpret_cast(excuteMethod.utf16()), reinterpret_cast(executeDir.utf16()), NULL, NULL, SW_NORMAL); +#else + QDesktopServices::openUrl(QUrl(executeDir, QUrl::TolerantMode)); +#endif + } + } +} + +void CMainWindow::on_outputConsolePressed() +{ + QStringList selectedItemList = getSelectedOutputItemNameList(); + int itemSelected = selectedItemList.size(); + + QString executeDir; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Console", "Can only open console from one path", QMessageBox::Ok); + } else { + QFileInfo fileInfo(selectedItemList.at(0)); + executeDir = fileInfo.absoluteDir().absolutePath(); + +#ifdef Q_OS_WIN + QString excuteMethod = "open"; + QString consoleCommnad = "cmd.exe"; + + ShellExecute(NULL, reinterpret_cast(excuteMethod.utf16()), reinterpret_cast(consoleCommnad.utf16()), NULL, reinterpret_cast(executeDir.utf16()), SW_NORMAL); +#else + executeDir = "--working-directory=" + executeDir; + QProcess::startDetached("gnome-terminal", QStringList(executeDir)); +#endif + } + } +} + +void CMainWindow::on_outputPropertiesPressed() +{ + QStringList selectedItemList = getSelectedOutputItemNameList(); + int itemSelected = selectedItemList.size(); + + QString executeDir; + + if (itemSelected > 0) { + if (itemSelected > 1) { + QMessageBox::information(this, "Properties", "Can only view properties for one file", QMessageBox::Ok); + } else { +#ifdef Q_OS_WIN + SHELLEXECUTEINFO execInfo; + QString excuteMethod = "properties"; + + ZeroMemory(&execInfo, sizeof(execInfo)); + execInfo.cbSize= sizeof(execInfo); + execInfo.hwnd= NULL; + execInfo.lpVerb= reinterpret_cast(excuteMethod.utf16()); + execInfo.fMask= SEE_MASK_INVOKEIDLIST; + execInfo.lpFile = reinterpret_cast(selectedItemList.at(0).utf16()); + + ShellExecuteEx(&execInfo); +#else + // not implemented +#endif + } + } +} + +void CMainWindow::queryTag(const QString& tag) +{ + QString tagDbFileName, inputFileName; + + QString resultHtml; + + QList resultList; + + QString resultItemSrcLine; + QFileInfo resultItemFileInfo; + + Qt::CaseSensitivity caseSensitivity = + actionSymbolCaseSensitive->isChecked() ? Qt::CaseSensitive + : Qt::CaseInsensitive; + + /* + webView->load(QUrl(search_lineEdit->text())); + webView->show(); + */ + + QString funcSignatureToPrint; + QString lineSrcBeforeToPrint; + QString lineSrcAfterToPrint; + + int i, j; + int lineSrcSize; + + QString lineNumStr; + QString modifiedLineSrc; + QString tagToQueryFiltered; + + if (!m_currentProfileItem.m_name.isEmpty()) { + + tagDbFileName = QString(QTagger::kQTAG_TAGS_DIR) + "/" + m_currentProfileItem.m_name + "/" + QString(QTagger::kQTAG_DEFAULT_TAGDBNAME); + inputFileName = QString(QTagger::kQTAG_TAGS_DIR) + "/" + m_currentProfileItem.m_name + "/" + QString(CSourceFileList::kFILE_LIST); + + m_tagger.queryTag(inputFileName, tagDbFileName, tag, tagToQueryFiltered, resultList, caseSensitivity); + + //QString tagToQuery = tag.toHtmlEscaped(); + QString tagToQuery = tagToQueryFiltered.toHtmlEscaped(); + + resultHtml = ""; + //resultHtml += ""; + resultHtml += ""; + resultHtml += "
";
+
+		QList::const_iterator indentIt;
+		int minIndent = 0;
+
+		foreach (const CTagResultItem& resultItem, resultList) {
+			// drive letter colon for first field
+
+            resultItemFileInfo.setFile(resultItem.filePath_);
+
+			resultItemSrcLine = resultItem.fileLineSrc_;
+			resultItemSrcLine = resultItemSrcLine.toHtmlEscaped();
+			resultItemSrcLine.replace(tagToQuery, "" + tagToQuery + "", Qt::CaseSensitive);
+
+			funcSignatureToPrint = "";
+			lineSrcBeforeToPrint = "";
+			lineSrcAfterToPrint = "";
+
+			if (resultItem.functionSignature_ != "") {
+				funcSignatureToPrint = "   " + resultItem.functionSignature_ + "";
+			}
+
+			minIndent = resultItem.lineSrcIndentLevel_;
+
+			if (resultItem.beforeIndentLevelList_.size() > 0) {
+				indentIt = std::min_element(resultItem.beforeIndentLevelList_.begin(), resultItem.beforeIndentLevelList_.end());
+				if (*indentIt < minIndent) {
+					minIndent = *indentIt;
+				}
+			}
+
+			if (resultItem.afterIndentLevelList_.size() > 0) {
+				indentIt = std::min_element(resultItem.afterIndentLevelList_.begin(), resultItem.afterIndentLevelList_.end());
+				if (*indentIt < minIndent) {
+					minIndent = *indentIt;
+				}
+			}
+
+			for (j = 0; j < resultItem.lineSrcIndentLevel_ - minIndent; j++) {
+				resultItemSrcLine = "   " + resultItemSrcLine;
+			}
+
+			lineSrcSize = resultItem.fileLineSrcBeforeList_.size();
+			if (lineSrcSize != 0) {
+				i = 0;
+
+				foreach (const QString& lineSrc, resultItem.fileLineSrcBeforeList_) {
+
+					lineNumStr = "" + QString::number(resultItem.fileLineNum_ - lineSrcSize + i) + " ";
+					modifiedLineSrc = lineSrc;
+					modifiedLineSrc = modifiedLineSrc.toHtmlEscaped();
+					modifiedLineSrc.replace(tagToQuery, "" + tagToQuery + "", Qt::CaseSensitive);
+
+					for (j = 0; j < resultItem.beforeIndentLevelList_.at(i) - minIndent; j++) {
+						modifiedLineSrc = "   " + modifiedLineSrc;
+					}
+
+					lineSrcBeforeToPrint += lineNumStr + modifiedLineSrc + "
"; + i++; + } + } + + if (resultItem.fileLineSrcAfterList_.size() != 0) { + i = 0; + + foreach (const QString& lineSrc, resultItem.fileLineSrcAfterList_) { + + lineNumStr = "" + QString::number(resultItem.fileLineNum_ + i + 1) + " "; + modifiedLineSrc = lineSrc; + modifiedLineSrc = modifiedLineSrc.toHtmlEscaped(); + modifiedLineSrc.replace(tagToQuery, "" + tagToQuery + "", Qt::CaseSensitive); + + for (j = 0; j < resultItem.afterIndentLevelList_.at(i) - minIndent; j++) { + modifiedLineSrc = "   " + modifiedLineSrc; + } + + lineSrcAfterToPrint += "
" + lineNumStr + modifiedLineSrc; + i++; + } + } + + resultHtml += QString("
") + + "" + + resultItemFileInfo.fileName() + "" + + funcSignatureToPrint + + "
" + + lineSrcBeforeToPrint + + + "" + QString::number(resultItem.fileLineNum_) + " " + + resultItemSrcLine + + + lineSrcAfterToPrint + + "
 
"; + + //qDebug() << "resultHtml = " << resultHtml << endl; + } + + resultHtml += "
"; + resultHtml += ""; + + /* + QString resultHtmlFileName = "result.html"; + QFile resultHtmlFile(resultHtmlFileName); + if (!resultHtmlFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Cannot open result html file (" << resultHtmlFileName << ") for writing!" << endl; + return; + } + + QTextStream resultHtmlStream(&resultHtmlFile); + */ + + //webView->load(QUrl::fromLocalFile(QApplication::applicationDirPath() + "/Html/index.html")); + +#ifdef ENABLE_SYMBOL_WEB_VIEW + webView->setHtml(resultHtml); + webView->show(); +#elif defined ENABLE_SYMBOL_RICH_TEXT_VIEW + symbol_textBrowser->setHtml(resultHtml); + symbol_textBrowser->show(); +#else + + textDocument_.setHtml(resultHtml); + + symbol_textBrowser->setDocument(&textDocument_); + symbol_textBrowser->show(); + /* + symbol_textBrowser->clear(); + symbol_textBrowser->appendHtml(resultHtml); + symbol_textBrowser->show(); + */ +#endif + + /* + resultHtmlStream << resultHtml; + resultHtmlStream.flush(); + resultHtmlFile.close(); + */ + } + +} + +void CMainWindow::on_searchButton_clicked() +{ + QString tagToQuery; + + tagToQuery = search_lineEdit->text(); + tagToQuery = tagToQuery.toHtmlEscaped(); + + queryTag(tagToQuery); +} + + +void CMainWindow::wheelEvent(QWheelEvent *e) +{ + QPoint p; + + p = profile_listView->mapFromGlobal(e->globalPos()); + + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + // no action + } else { + // no action + } + } + QMainWindow::wheelEvent(e); +} + + +void CMainWindow::appendLogList(TRACE_LEVEL level, const QString& msg) +{ + QString qStrBuf; + + switch (level) { + case TRACE_DEBUG: qStrBuf = "DEBUG: " + msg; break; + case TRACE_INFO: qStrBuf = "INFO: " + msg; break; + case TRACE_WARNING: qStrBuf = "WARNING: " + msg; break; + case TRACE_ERROR: qStrBuf = "ERROR: " + msg; break; + } +} + +void CMainWindow::keyPressEvent(QKeyEvent *event) +{ + + if (filePattern_lineEdit->hasFocus()) { + switch (event->key()) { + case Qt::Key_Up: + output_listView->setFocus(); + break; + case Qt::Key_Down: + output_listView->setFocus(); + break; + } + } else if (profilePattern_lineEdit->hasFocus()) { + switch (event->key()) { + case Qt::Key_Up: + profile_listView->setFocus(); + break; + case Qt::Key_Down: + profile_listView->setFocus(); + break; + } + } + + QMainWindow::keyPressEvent(event); +} + + + + diff --git a/Display/CMainWindow.h b/Display/CMainWindow.h new file mode 100644 index 0000000..c64712d --- /dev/null +++ b/Display/CMainWindow.h @@ -0,0 +1,219 @@ +#ifndef CMAINWINDOW_H +#define CMAINWINDOW_H + +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include + +#include "Model/CProfileManager.h" +#include "Model/CProfileLoadThread.h" +#include "Model/CProfileUpdateThread.h" + +#include "Model/CGroupLoadThread.h" + +#include "Model/CProfileListModel.h" +#include "Model/CGroupListModel.h" +#include "Model/COutputListModel.h" + +#include "Model/CConfigManager.h" + +#include "ui_mainWindow.h" + +#include "Utils/commonType.h" + +class CMainWindow : public QMainWindow, private Ui::mainWindow +{ + Q_OBJECT + +public: + CMainWindow(QWidget* parent = 0); + virtual ~CMainWindow() {} + + void setSplitterSizes(const QList& splitterSizeList); + void restoreTabWidgetPos(); + +public slots: + void loadProfileList(); + void loadGroupList(); + void loadOutputList(); + +private slots: + void on_newProfileButton_clicked(); + void on_loadProfileButton_clicked(); + void on_updateProfileButton_clicked(); + void on_rebuildTagProfileButton_clicked(); + + void on_editProfileButton_clicked(); + void on_deleteProfileButton_clicked(); + + void on_exploreProfileButton_clicked(); + void on_consoleProfileButton_clicked(); + + + void on_newGroupButton_clicked(); + void on_loadGroupButton_clicked(); + void on_updateGroupButton_clicked(); + void on_editGroupButton_clicked(); + void on_deleteGroupButton_clicked(); + + void on_aboutButton_clicked(); + void on_clearOutputButton_clicked(); + void on_clearLogButton_clicked(); + void on_actionAlways_on_top_toggled(); + void on_actionTransparent_toggled(); + void on_actionToolbar_toggled(); + + void on_actionProfile_Panel_toggled(); + void on_actionFile_Panel_toggled(); + + void on_actionExit_triggered(); + void on_actionSetting_triggered(); + + void on_outputEditPressed(); + void on_outputCopyPressed(); + void on_outputExplorePressed(); + void on_outputConsolePressed(); + void on_outputPropertiesPressed(); + + void on_searchButton_clicked(); + + void wheelEvent(QWheelEvent *e); + + void updateTagBuildProgress(int percentage); + void updateCancelledTagBuild(); + + void updateProfileLoadProgress(int percentage); + void updateGroupLoadProgress(int percentage); + + void on_errorDuringRun(const QString& cmdStr); + + void on_profilePatternLineEditShortcutPressed(); + void on_groupPatternLineEditShortcutPressed(); + + void on_filePatternLineEditShortcutPressed(); + void on_searchLineEditShortcutPressed(); + + void on_infoTabWidgetToolBn_clicked(); + + void profileFilterRegExpChanged(); + void groupFilterRegExpChanged(); + + void fileFilterRegExpChanged(); + + void searchLineEditChanged(); + + void on_symbolSearchFrameShortcutPressed(); + void on_nextSymbolButton_clicked(); + void on_previousSymbolButton_clicked(); + + void frameSymbolLineEditChanged(); + + void on_cancelTagUpdate(); + + void contextMenuEvent(QContextMenuEvent* event); + void appendLogList(TRACE_LEVEL level, const QString& msg); + void keyPressEvent(QKeyEvent *event); + + void queryTag(const QString& tag); + +private: + void updateProfileListWidget(); + void updateGroupListWidget(); + void updateOutputListWidget(); + + void createActions(); + + QStringList getSelectedProfileItemNameList(); + QStringList getSelectedGroupItemNameList(); + QStringList getSelectedOutputItemNameList(); + + void setAlwaysOnTop(bool enable); + void setTransparency(bool enable); + + void saveWidgetPosition(); + + void closeEvent(QCloseEvent *event); + + QProgressBar m_progressBar; + + QActionGroup *filterMethodGroup; + QRegExp::PatternSyntax patternSyntax_; + + CProfileListModel* m_profileListModel; + CGroupListModel* m_groupListModel; + COutputListModel* m_outputListModel; + + CProfileLoadThread m_profileLoadThread; + CProfileUpdateThread m_profileUpdateThread; + + CGroupLoadThread m_groupLoadThread; + + QSortFilterProxyModel* m_profileListProxyModel; + QItemSelectionModel* m_profileListSelectionModel; + + QSortFilterProxyModel* m_groupListProxyModel; + QItemSelectionModel* m_groupListSelectionModel; + + QTimeLine m_timeLine; + + QShortcut* profilePatternLineEditShortcut; + QShortcut* groupPatternLineEditShortcut; + + QShortcut* fileSearchShortcut; + QShortcut* tagSearchShortcut; + + QShortcut* outputExploreShortcut; + QShortcut* outputConsoleShortcut; + QShortcut* outputPropertiesShortcut; + + QShortcut* profileLoadShortcut; + QShortcut* profileUpdateShortcut; + + QShortcut* symbolSearchFrameShortcut; + QShortcut* nextSymbolSearchShortcut; + QShortcut* previousSymbolSearchShortcut; + +#ifdef Q_OS_WIN + QShortcut* previousSymbolSearchShortcut_win; +#endif + + QToolButton *m_pInfoTabWidgetToolBn; + + bool m_bTagBuildInProgress; + + QSize m_priorMainTabWidgetSize; + int infoTabWidgetWidth; + + CProfileItem m_currentProfileItem; + CGroupItem m_currentGroupItem; + + CConfigManager* m_confManager; + + QTagger m_tagger; + + T_OutputItemList m_outputItemList; + + QCompleter m_completer; + QStringListModel m_stringListModel; + + QTextDocument textDocument_; + QPlainTextDocumentLayout* textLayout_; + +}; +#endif // CMAINWINDOW_H + + diff --git a/Display/COutputListWidget.cpp b/Display/COutputListWidget.cpp new file mode 100644 index 0000000..10218b9 --- /dev/null +++ b/Display/COutputListWidget.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#include + +#include "COutputListWidget.h" + +COutputListWidget::COutputListWidget(QWidget *parent) +: QTreeView(parent) +{ + QFont currentFont = static_cast (this)->font(); + fileFontSize_ = currentFont.pointSize(); +} + +void COutputListWidget::setOutputListModel(COutputListModel *outputListModel) +{ + m_outputListModel = outputListModel; +} + +void COutputListWidget::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + m_dragStartPosition = event->pos(); + } + QTreeView::mousePressEvent(event); +} + +void COutputListWidget::mouseDoubleClickEvent(QMouseEvent* event) +{ + emit outputItemTriggered(); + QTreeView::mouseDoubleClickEvent(event); +} + +void COutputListWidget::keyPressEvent(QKeyEvent* event) +{ + if (event->key() == Qt::Key_Return) { + emit outputItemTriggered(); + } else if ((event->key() == Qt::Key_Equal) && (event->modifiers() == Qt::ControlModifier)) { + fileZoomIn(); + } else if ((event->key() == Qt::Key_Minus) && (event->modifiers() == Qt::ControlModifier)) { + fileZoomOut(); + } + QTreeView::keyPressEvent(event); +} + +void COutputListWidget::updateOutputFont(const QFont& outputFont) +{ + QFont currentFont = static_cast (this)->font(); + + if (currentFont != outputFont) { + static_cast (this)->setFont(outputFont); + + fileFontSize_ = outputFont.pointSize(); + updateOutputListWidget(); + } +} + + +QStringList COutputListWidget::getSelectedItemNameList() +{ + QModelIndexList indexSelectedList; + QModelIndex indexSelected, mappedIndex; + int rowSelected; + QStandardItem* itemSelected; + + QString outputItemName; + QStringList outputItemNameList; + + QSortFilterProxyModel* proxyModel; + QItemSelectionModel* selectModel; + + proxyModel = static_cast (model()); + selectModel = static_cast (selectionModel()); + + // get selected items index list + indexSelectedList = selectModel->selectedIndexes(); + + foreach (indexSelected, indexSelectedList) { + // map back from proxy model + mappedIndex = proxyModel->mapToSource(indexSelected); + + rowSelected = mappedIndex.row(); + + if (indexSelected.isValid()) { + itemSelected = m_outputListModel->item(rowSelected, 0); + if (itemSelected != 0) { + outputItemName = itemSelected->text(); + }; + } + + // as all items in the same row with differnt columns will also be returned in selectedIndexes + if (!outputItemNameList.contains(outputItemName)) { + // not add output name to the list if already added + outputItemNameList += outputItemName; + } + } + + return outputItemNameList; +} + +void COutputListWidget::mouseMoveEvent(QMouseEvent *event) +{ + if (!(event->buttons() & Qt::LeftButton)) { + return; + } + if ((event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { + return; + } + + QList urlList; + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + + QString filePath; + QStringList filePathList; + + filePathList = getSelectedItemNameList(); + + foreach (filePath, filePathList) { + qDebug() << filePath; + QUrl url = QUrl::fromLocalFile(filePath); + urlList.append(url); + } + + mimeData->setUrls(urlList); + drag->setMimeData(mimeData); + + Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); + + QTreeView::mouseMoveEvent(event); +} + +void COutputListWidget::updateOutputListWidget() +{ + resizeColumnToContents(0); + resizeColumnToContents(1); + resizeColumnToContents(2); +} + +void COutputListWidget::fileZoomIn() +{ + fileFontSize_++; + QFont fnt = static_cast (this)->font(); + fnt.setPointSize(fileFontSize_); + static_cast (this)->setFont(fnt); + + updateOutputListWidget(); +} + +void COutputListWidget::fileZoomOut() +{ + if (fileFontSize_ > 1) { + fileFontSize_--; + QFont fnt = static_cast (this)->font(); + fnt.setPointSize(fileFontSize_); + static_cast (this)->setFont(fnt); + } + + updateOutputListWidget(); +} + + +void COutputListWidget::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + fileZoomIn(); + } else { + fileZoomOut(); + } + } + QTreeView::wheelEvent(e); +} + + diff --git a/Display/COutputListWidget.h b/Display/COutputListWidget.h new file mode 100644 index 0000000..1f51b5a --- /dev/null +++ b/Display/COutputListWidget.h @@ -0,0 +1,50 @@ +#ifndef COUTPUT_LIST_WIDGET_H +#define COUTPUT_LIST_WIDGET_H + +#include +#include +#include + +#include + +#include "Model/COutputListModel.h" + +class COutputListWidget : public QTreeView +{ + Q_OBJECT + +public: + COutputListWidget(QWidget *parent = 0); + + void setOutputListModel(COutputListModel *outputModel); + + void mousePressEvent(QMouseEvent *event); + + void mouseDoubleClickEvent(QMouseEvent* event); + void keyPressEvent(QKeyEvent* event); + + void updateOutputFont(const QFont& outputFont); + + void mouseMoveEvent(QMouseEvent *event); + + void wheelEvent(QWheelEvent *e); + + QPoint m_dragStartPosition; + +signals: + void outputItemTriggered(); + +private: + void updateOutputListWidget(); + void fileZoomIn(); + void fileZoomOut(); + + QStringList getSelectedItemNameList(); + + COutputListModel* m_outputListModel; + + long fileFontSize_; + +}; + +#endif // COUTPUT_LIST_WIDGET_H diff --git a/Display/CProfileDlg.cpp b/Display/CProfileDlg.cpp new file mode 100644 index 0000000..c294e7c --- /dev/null +++ b/Display/CProfileDlg.cpp @@ -0,0 +1,114 @@ +#include +#include + +#include +#include + +#include "CProfileDlg.h" + +CProfileDlg::CProfileDlg(QWidget* parent) +: QDialog(parent) +{ + setupUi(this); + + currentProfileName_ = ""; +} + +CProfileDlg::CProfileDlg(const QString& profileName, const CProfileItem& profileItem, QWidget* parent) +: QDialog(parent) +{ + setupUi(this); + + currentProfileName_ = profileName; + + profileName_lineEdit->setText(profileItem.m_name); + srcDir_lineEdit->setText(profileItem.m_srcDir); + srcFileMask_lineEdit->setText(profileItem.m_srcMask); + headerfileMask_lineEdit->setText(profileItem.m_headerMask); + labels_lineEdit->setText(profileItem.m_labels); + + // connect slot only after when CProfileDlg has already been loaded and initial content filled in + QObject::connect(profileName_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(profileContentChanged())); + QObject::connect(srcDir_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(profileContentChanged())); + QObject::connect(headerfileMask_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(profileContentChanged())); + QObject::connect(srcFileMask_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(profileContentChanged())); + QObject::connect(labels_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(profileContentChanged())); + +} + +void CProfileDlg::on_okButton_clicked() +{ + on_applyButton_clicked(); + this->done(QDialog::Accepted); +} + +void CProfileDlg::on_cancelButton_clicked() +{ + this->done(QDialog::Rejected); +} + +void CProfileDlg::on_applyButton_clicked() +{ + CProfileItem modifiedItem; + QDateTime currDateTime; + + // input error checking + if (profileName_lineEdit->text() == "") { + QMessageBox::warning(this, "Profile", "Profile name cannot be empty!", QMessageBox::Ok); + return; + } + if (srcDir_lineEdit->text() == "") { + QMessageBox::warning(this, "Profile", "Source directory cannot be empty!", QMessageBox::Ok); + return; + } + if ((srcFileMask_lineEdit->text() == "") && (headerfileMask_lineEdit->text() == "")) { + QMessageBox::warning(this, "Profile", "Source and header file mask cannot be both empty!", QMessageBox::Ok); + return; + } + // labels can be empty so no checking + + modifiedItem.m_name = profileName_lineEdit->text(); + modifiedItem.m_srcDir = srcDir_lineEdit->text(); + modifiedItem.m_srcMask = srcFileMask_lineEdit->text(); + modifiedItem.m_headerMask = headerfileMask_lineEdit->text(); + + currDateTime = QDateTime::currentDateTime(); + + modifiedItem.m_profileCreateDateTime = currDateTime.toString("dd/MM/yyyy hh:mm:ss"); + + modifiedItem.m_labels = labels_lineEdit->text(); + + if (currentProfileName_ == "") { // new Profile + CProfileManager::getInstance()->updateProfileItem(modifiedItem.m_name, modifiedItem); + } else { + // use currentProfileName_ for updateProfileItem as name may have be changed + CProfileManager::getInstance()->updateProfileItem(currentProfileName_, modifiedItem); + } + + setWindowModified(false); +} + +void CProfileDlg::on_srcDir_toolBn_clicked() +{ + QString sourceDir; + + if (srcDir_lineEdit->text() != "") { + sourceDir = srcDir_lineEdit->text(); + } else { + sourceDir = QDir::currentPath(); + } + + QString directory = QFileDialog::getExistingDirectory(this, + tr("Source directory"), sourceDir); + if (directory != "") { + srcDir_lineEdit->setText(directory); + } +} + +void CProfileDlg::profileContentChanged() +{ + applyButton->setEnabled(true); + setWindowModified(true); +} + + diff --git a/Display/CProfileDlg.h b/Display/CProfileDlg.h new file mode 100644 index 0000000..58267cb --- /dev/null +++ b/Display/CProfileDlg.h @@ -0,0 +1,30 @@ +#ifndef CPROFILEDLG_H +#define CPROFILEDLG_H + +#include +#include "Model/CProfileItem.h" +#include "Model/CProfileManager.h" +#include "ui_profileDialog.h" + +class CProfileDlg : public QDialog, private Ui::profileDialog +{ + Q_OBJECT + +public: + CProfileDlg(QWidget* parent = 0); + CProfileDlg(const QString& profileName, const CProfileItem& profileItem, QWidget* parent = 0); + + virtual ~CProfileDlg() {} +private slots: + void on_okButton_clicked(); + void on_cancelButton_clicked(); + void on_applyButton_clicked(); + void on_srcDir_toolBn_clicked(); + + void profileContentChanged(); +private: + QString currentProfileName_; +}; +#endif // CPROFILEDLG_H + + diff --git a/Display/CProfileListWidget.cpp b/Display/CProfileListWidget.cpp new file mode 100644 index 0000000..38f2f74 --- /dev/null +++ b/Display/CProfileListWidget.cpp @@ -0,0 +1,86 @@ +#include "CProfileListWidget.h" + +CProfileListWidget::CProfileListWidget(QWidget *parent) +: QTreeView(parent) +{ + QFont currentFont = static_cast (this)->font(); + + profileFontSize_ = currentFont.pointSize(); +} + +void CProfileListWidget::updateProfileListWidget() +{ + resizeColumnToContents(0); + resizeColumnToContents(1); + resizeColumnToContents(2); + resizeColumnToContents(3); +} + +void CProfileListWidget::mouseDoubleClickEvent(QMouseEvent* event) +{ + emit profileItemTriggered(); + QTreeView::mouseDoubleClickEvent(event); +} + +void CProfileListWidget::keyPressEvent(QKeyEvent* event) +{ + if (event->key() == Qt::Key_Return) { + emit profileItemTriggered(); + } else if ((event->key() == Qt::Key_Equal) && (event->modifiers() == Qt::ControlModifier)) { + profileZoomIn(); + } else if ((event->key() == Qt::Key_Minus) && (event->modifiers() == Qt::ControlModifier)) { + profileZoomOut(); + } + + QTreeView::keyPressEvent(event); +} + +void CProfileListWidget::updateProfileFont(const QFont& profileFont) +{ + QFont currentFont = static_cast (this)->font(); + + if (currentFont != profileFont) { + static_cast (this)->setFont(profileFont); + profileFontSize_ = profileFont.pointSize(); + updateProfileListWidget(); + } +} + +void CProfileListWidget::profileZoomIn() +{ + profileFontSize_++; + QFont fnt = static_cast (this)->font();; + fnt.setPointSize(profileFontSize_); + static_cast (this)->setFont(fnt); + + updateProfileListWidget(); +} + +void CProfileListWidget::profileZoomOut() +{ + if (profileFontSize_ > 1) { + profileFontSize_--; + QFont fnt = static_cast (this)->font(); + fnt.setPointSize(profileFontSize_); + static_cast (this)->setFont(fnt); + + updateProfileListWidget(); + } +} + +void CProfileListWidget::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + profileZoomIn(); + } else { + profileZoomOut(); + } + } + QTreeView::wheelEvent(e); +} + + + + diff --git a/Display/CProfileListWidget.h b/Display/CProfileListWidget.h new file mode 100644 index 0000000..31630f8 --- /dev/null +++ b/Display/CProfileListWidget.h @@ -0,0 +1,33 @@ +#ifndef CPROFILE_LIST_WIDGET_H +#define CPROFILE_LIST_WIDGET_H + +#include +#include + +class CProfileListWidget : public QTreeView +{ + Q_OBJECT + +public: + CProfileListWidget(QWidget *parent = 0); + + void mouseDoubleClickEvent(QMouseEvent* event); + void keyPressEvent(QKeyEvent* event); + + void wheelEvent(QWheelEvent *e); + + void updateProfileFont(const QFont& profileFont); + +signals: + void profileItemTriggered(); + +private: + long profileFontSize_; + + void updateProfileListWidget(); + + void profileZoomIn(); + void profileZoomOut(); +}; + +#endif // CPROFILE_LIST_WIDGET_H diff --git a/Display/CSearchTextBrowser.cpp b/Display/CSearchTextBrowser.cpp new file mode 100644 index 0000000..5948f8b --- /dev/null +++ b/Display/CSearchTextBrowser.cpp @@ -0,0 +1,112 @@ +#include "CSearchTextBrowser.h" +#include + +#ifdef Q_OS_WIN + #include +#endif + +CSearchTextBrowser::CSearchTextBrowser(QWidget *parent) + : QTextBrowser(parent) +{ + setLineWrapMode(QTextEdit::NoWrap); + + selectAllShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); + connect(selectAllShortcut, SIGNAL(activated()), this, SLOT(on_selectAllPressed())); + +// page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); + connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(on_urlClicked(const QUrl &))); + + m_confManager = CConfigManager::getInstance(); + + // default zoom level + zoomIn(3); + + // no open links by QTextbrowser itself + setOpenLinks(false); +} + +void CSearchTextBrowser::textZoomIn() +{ + zoomIn(1); +} + +void CSearchTextBrowser::textZoomOut() +{ + zoomOut(1); +} + +bool CSearchTextBrowser::findText(const QString & subString, QTextDocument::FindFlags options) +{ + return QTextBrowser::find(subString, options); +} + +void CSearchTextBrowser::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + textZoomIn(); + } else { + textZoomOut(); + } + QTextBrowser::wheelEvent(e); + } else { + QTextBrowser::wheelEvent(e); + } +} + +void CSearchTextBrowser::contextMenuEvent(QContextMenuEvent *event) +{ +/* + QMenu menu(this); + + menu.addAction(pageAction(QWebPage::SelectAll)); + menu.addAction(pageAction(QWebPage::Copy)); + + menu.exec(event->globalPos()); +*/ + + // bypass original context menu, e.g. reload + //QWebView::contextMenuEvent(event); +} + +void CSearchTextBrowser::on_selectAllPressed() +{ + selectAll(); +} + +void CSearchTextBrowser::on_urlClicked(const QUrl& urlClicked) +{ +// QMessageBox::information(this, "CSearchWebView", urlClicked.path(), QMessageBox::Ok); + + QString filePath = urlClicked.path(); + filePath.remove(0, 1); // remove beginning "/" character + + filePath = "\"" + filePath + "\""; // add quote, needed for gvim handling for filename with space + + QString executeDir = ""; + + QString lineNum = urlClicked.fragment(); + lineNum.remove(0, 4); // remove beginning "line" string + +#ifdef Q_OS_WIN + QString cmdParam; + + QString executeMethod = "open"; + QString consoleCommnad = m_confManager->getAppSettingValue("DefaultEditor").toString(); + + if (consoleCommnad.endsWith("gvim.exe")) { + cmdParam = "+" + lineNum + " " + filePath; // +lineNum fileName + } else { + cmdParam = filePath; // fileName + } + + ShellExecute(NULL, reinterpret_cast(executeMethod.utf16()), reinterpret_cast(consoleCommnad.utf16()), + reinterpret_cast (cmdParam.utf16()), reinterpret_cast(executeDir.utf16()), SW_NORMAL); +#else + // not implemented +#endif +} + + + diff --git a/Display/CSearchTextBrowser.h b/Display/CSearchTextBrowser.h new file mode 100644 index 0000000..6890392 --- /dev/null +++ b/Display/CSearchTextBrowser.h @@ -0,0 +1,42 @@ +#ifndef CSEARCH_TEXT_BROWSER_H +#define CSEARCH_TEXT_BROWSER_H + +#include +#include +#include +#include + +#include "Model/CConfigManager.h" + +class CSearchTextBrowser : public QTextBrowser +{ + Q_OBJECT + +public: + CSearchTextBrowser(QWidget *parent = 0); + + void textZoomIn(); + void textZoomOut(); + + bool findText(const QString & subString, QTextDocument::FindFlags options); + +public slots: + void wheelEvent(QWheelEvent *e); + void contextMenuEvent(QContextMenuEvent *event); + +private: + QShortcut* selectAllShortcut; + + CConfigManager* m_confManager; + +private slots: + void on_selectAllPressed(); + void on_urlClicked(const QUrl &); + + +}; + + + +#endif // CSEARCH_TEXT_BROWSER_H + diff --git a/Display/CSearchWebView.cpp b/Display/CSearchWebView.cpp new file mode 100644 index 0000000..b11a995 --- /dev/null +++ b/Display/CSearchWebView.cpp @@ -0,0 +1,103 @@ +#include "CSearchWebView.h" +#include + +#ifdef Q_OS_WIN + #include +#endif + +CSearchWebView::CSearchWebView(QWidget *parent) + : QWebView(parent) +{ + selectAllShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); + connect(selectAllShortcut, SIGNAL(activated()), this, SLOT(on_selectAllPressed())); + + page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); + connect(this, SIGNAL(linkClicked(const QUrl &)), this, SLOT(on_urlClicked(const QUrl &))); + + m_confManager = CConfigManager::getInstance(); +} + +void CSearchWebView::webZoomIn() +{ + qreal currentZoomFactor = zoomFactor(); + + setZoomFactor(currentZoomFactor * 1.1); +} + +void CSearchWebView::webZoomOut() +{ + qreal currentZoomFactor = zoomFactor(); + + setZoomFactor(currentZoomFactor * 0.9); +} + +bool CSearchWebView::findText(const QString & subString, QWebPage::FindFlags options) +{ + return QWebView::findText(subString, options); +} + +void CSearchWebView::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() == Qt::ControlModifier) { + e->accept(); + if (e->delta() > 0) { + webZoomIn(); + } else { + webZoomOut(); + } + QWebView::wheelEvent(e); + } else { + QWebView::wheelEvent(e); + } +} + +void CSearchWebView::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu menu(this); + + menu.addAction(pageAction(QWebPage::SelectAll)); + menu.addAction(pageAction(QWebPage::Copy)); + menu.exec(event->globalPos()); + + // bypass original context menu, e.g. reload + //QWebView::contextMenuEvent(event); +} + +void CSearchWebView::on_selectAllPressed() +{ + this->triggerPageAction(QWebPage::SelectAll); +} + +void CSearchWebView::on_urlClicked(const QUrl& urlClicked) +{ +// QMessageBox::information(this, "CSearchWebView", urlClicked.path(), QMessageBox::Ok); + + QString filePath = urlClicked.path(); + filePath.remove(0, 1); // remove beginning "/" character + + QString executeDir = ""; + + QString lineNum = urlClicked.fragment(); + lineNum.remove(0, 4); // remove beginning "line" string + +#ifdef Q_OS_WIN + QString cmdParam; + + QString executeMethod = "open"; + QString consoleCommnad = m_confManager->getAppSettingValue("DefaultEditor").toString(); + + if (consoleCommnad.endsWith("gvim.exe")) { + cmdParam = "+" + lineNum + " " + filePath; // +lineNum fileName + } else { + cmdParam = filePath; // fileName + } + + ShellExecute(NULL, reinterpret_cast(executeMethod.utf16()), reinterpret_cast(consoleCommnad.utf16()), + reinterpret_cast (cmdParam.utf16()), reinterpret_cast(executeDir.utf16()), SW_NORMAL); +#else + // not implemented +#endif +} + + + diff --git a/Display/CSearchWebView.h b/Display/CSearchWebView.h new file mode 100644 index 0000000..6ec7265 --- /dev/null +++ b/Display/CSearchWebView.h @@ -0,0 +1,44 @@ +#ifndef CSEARCH_WEB_VIEW_H +#define CSEARCH_WEB_VIEW_H + +#include +#include +#include +#include + +#include + +#include "Model/CConfigManager.h" + +class CSearchWebView : public QWebView +{ + Q_OBJECT + +public: + CSearchWebView(QWidget *parent = 0); + + void webZoomIn(); + void webZoomOut(); + + bool findText(const QString & subString, QWebPage::FindFlags options); + +public slots: + void wheelEvent(QWheelEvent *e); + void contextMenuEvent(QContextMenuEvent *event); + +private: + QShortcut* selectAllShortcut; + + CConfigManager* m_confManager; + +private slots: + void on_selectAllPressed(); + void on_urlClicked(const QUrl &); + + +}; + + + +#endif // CSEARCH_WEB_VIEW_H + diff --git a/Model/CConfigManager.cpp b/Model/CConfigManager.cpp new file mode 100644 index 0000000..4b57ec4 --- /dev/null +++ b/Model/CConfigManager.cpp @@ -0,0 +1,66 @@ +#include "CConfigManager.h" + +CConfigManager* CConfigManager::m_manager = 0; + +CConfigManager* CConfigManager::getInstance() +{ + if (m_manager == 0) { + m_manager = new CConfigManager(); + } + return m_manager; +} + +CConfigManager::CConfigManager() +{ + confSetting = new QSettings("blink.ini", QSettings::IniFormat); +} + +QVariant CConfigManager::getAppSettingValue(const QString& key) const +{ + if (key == "TagDir") { // default directory for storing tags + return confSetting->value("Setting/" + key, "tags"); + } else{ + return confSetting->value("Setting/" + key); + } +} + +QVariant CConfigManager::getAppSettingValue(const QString& key, const QVariant &defaultValue) const +{ + if (key == "TagDir") { // default directory for storing tags + return confSetting->value("Setting/" + key, "tags"); + } else { + return confSetting->value("Setting/" + key, defaultValue); + } +} + +void CConfigManager::setAppSettingValue(const QString& key, const QVariant& val) +{ + confSetting->setValue("Setting/" + key, val); +} + +QVariant CConfigManager::getValue(const QString& section, const QString& key) const +{ + return confSetting->value(section + "/" + key); +} + +QVariant CConfigManager::getValue(const QString& section, const QString& key, const QVariant &defaultValue) const +{ + return confSetting->value(section + "/" + key, defaultValue); +} + +void CConfigManager::setValue(const QString& section, const QString& key, const QVariant& val) +{ + confSetting->setValue(section + "/" + key, val); +} + +void CConfigManager::updateConfig() +{ + confSetting->sync(); +} + + + + + + + diff --git a/Model/CConfigManager.h b/Model/CConfigManager.h new file mode 100644 index 0000000..5720853 --- /dev/null +++ b/Model/CConfigManager.h @@ -0,0 +1,36 @@ +#ifndef CCONFIG_MANAGER_H +#define CCONFIG_MANAGER_H + +#include +#include +#include + +class CConfigManager: public QObject +{ + Q_OBJECT +public: + CConfigManager(); + + virtual ~CConfigManager() {}; + + static CConfigManager* getInstance(); + + QVariant getAppSettingValue(const QString& key) const; + QVariant getAppSettingValue(const QString& key, const QVariant &defaultValue) const; + + void setAppSettingValue(const QString& key, const QVariant& val); + + QVariant getValue(const QString& section, const QString& key) const; + QVariant getValue(const QString& section, const QString& key, const QVariant &defaultValue) const; + + void setValue(const QString& section, const QString& key, const QVariant& val); + + void updateConfig(); + +private: + static CConfigManager* m_manager; + QSettings* confSetting; +}; + + +#endif // CCONFIG_MANAGER_H diff --git a/Model/CGroupItem.cpp b/Model/CGroupItem.cpp new file mode 100644 index 0000000..8bd5b7c --- /dev/null +++ b/Model/CGroupItem.cpp @@ -0,0 +1,27 @@ +#include "CGroupItem.h" + +CGroupItem::CGroupItem() +{ + m_name = ""; + m_profileList = ""; + m_tagUpdateDateTime = ""; + m_groupCreateDateTime = ""; + m_labels = ""; +} + +CGroupItem::CGroupItem(const QString& name, const QString& profileList, const QString& tagUpdateDateTime, + const QString& groupCreateDateTime, const QString& labels) +{ + m_name = name; + + m_profileList = profileList; + + m_tagUpdateDateTime = tagUpdateDateTime; + m_groupCreateDateTime = groupCreateDateTime; + + m_labels = labels; +} + + + + diff --git a/Model/CGroupItem.h b/Model/CGroupItem.h new file mode 100644 index 0000000..78fdd33 --- /dev/null +++ b/Model/CGroupItem.h @@ -0,0 +1,30 @@ +#ifndef CGROUP_ITEM_H +#define CGROUP_ITEM_H + +#include +#include +#include + +class CGroupItem +{ +public: + + CGroupItem(); + CGroupItem(const QString& name, const QString& profileList, const QString& tagUpdateDateTime, + const QString& groupCreateDateTime, const QString& labels); + + QString m_name, + m_profileList, + + m_tagUpdateDateTime, + m_groupCreateDateTime, + m_labels; + + virtual ~CGroupItem() {}; +}; + +#endif // CGROUP_ITEM_H + + + + diff --git a/Model/CGroupListModel.cpp b/Model/CGroupListModel.cpp new file mode 100644 index 0000000..5fdef69 --- /dev/null +++ b/Model/CGroupListModel.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include + +#include "CGroupListModel.h" +#include "Display/CGroupDlg.h" + +CGroupListModel::CGroupListModel(QObject *parent) + : QStandardItemModel(0, 4, parent) +{ + m_parent = static_cast (parent); + + // view when list is empty, view with content in CMainWindow::loadGroupList() + setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + setHeaderData(1, Qt::Horizontal, QObject::tr("Tag Update Datetime")); + setHeaderData(2, Qt::Horizontal, QObject::tr("Group Create Datetime")); + setHeaderData(3, Qt::Horizontal, QObject::tr("Labels")); +} + +void CGroupListModel::addGroupItem(const CGroupItem& groupItem) +{ + QDateTime tagUpdateDateTime, groupCreateDatetime; + + insertRow(0); + + setData(index(0, 0), groupItem.m_name); + + if (groupItem.m_tagUpdateDateTime == "") { + setData(index(0, 1), ""); + } else { + tagUpdateDateTime = QDateTime::fromString(groupItem.m_tagUpdateDateTime, "dd/MM/yyyy HH:mm:ss"); + setData(index(0, 1), tagUpdateDateTime); + } + + if (groupItem.m_groupCreateDateTime == "") { + setData(index(0, 2), ""); + } else { + groupCreateDatetime = QDateTime::fromString(groupItem.m_groupCreateDateTime, "dd/MM/yyyy HH:mm:ss"); + setData(index(0, 2), groupCreateDatetime); + } + + setData(index(0, 3), groupItem.m_labels); + +} + +bool CGroupListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + QList urlList; + + QFileInfo info; + QString fName; + + CGroupItem droppedItem; + + urlList = data->urls(); // retrieve list of urls + + foreach(QUrl url, urlList) // iterate over list + { + //qDebug("url = %s", url.toString().toLatin1().constData()); + fName = url.toLocalFile(); + //qDebug("fName = %s", fName.toLatin1().constData()); + info.setFile(fName); + + if (info.isDir()) { + + // fill default value according to item dropped + droppedItem.m_name = info.fileName(); + + QDialog* dialog = new CGroupDlg(droppedItem.m_name, droppedItem, m_parent); + dialog->exec(); + + } else { + QMessageBox::information(m_parent, "Add group", "Only folder is supported!", QMessageBox::Ok); + } + } + return true; +} + +QStringList CGroupListModel::mimeTypes () const +{ + QStringList qstrList; + // list of accepted mime types accepted + qstrList.append("text/uri-list"); + return qstrList; +} + +Qt::DropActions CGroupListModel::supportedDropActions () const +{ + // actions supported + return Qt::CopyAction | Qt::MoveAction; +} + + + diff --git a/Model/CGroupListModel.h b/Model/CGroupListModel.h new file mode 100644 index 0000000..24b4608 --- /dev/null +++ b/Model/CGroupListModel.h @@ -0,0 +1,25 @@ +#ifndef CGROUP_LIST_MODEL_H +#define CGROUP_LIST_MODEL_H + +#include +#include "Model/CGroupItem.h" + +class CGroupListModel: public QStandardItemModel +{ + Q_OBJECT + +public: + CGroupListModel(QObject *parent = 0); + + void addGroupItem(const CGroupItem& groupItem); + + bool dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent); + QStringList mimeTypes() const; + + Qt::DropActions supportedDropActions() const; + + QWidget* m_parent; +}; + +#endif // CGROUP_LIST_MODEL_H diff --git a/Model/CGroupLoadThread.cpp b/Model/CGroupLoadThread.cpp new file mode 100644 index 0000000..d9d7fce --- /dev/null +++ b/Model/CGroupLoadThread.cpp @@ -0,0 +1,111 @@ +#include "CGroupLoadThread.h" + +CGroupLoadThread::CGroupLoadThread(QObject *parent) + : QThread(parent) +{ + m_taggerPtr = NULL; + m_outputItemListPtr = NULL; +} + +void CGroupLoadThread::setTaggerPtr(QTagger* taggerPtr) +{ + m_taggerPtr = taggerPtr; +} + +void CGroupLoadThread::setOutputItemListPtr(T_OutputItemList* outputItemListPtr) +{ + m_outputItemListPtr = outputItemListPtr; +} + +void CGroupLoadThread::setCurrentGroupItem(const CGroupItem& groupItem) +{ + m_groupItem = groupItem; +} + +CGroupItem CGroupLoadThread::getCurrentGroupItem() +{ + return m_groupItem; +} + + +bool CGroupLoadThread::runCommand(const QString& program, const QString& workDir, const QString& redirectFile) +{ + QString errStr; + CRunCommand::ENUM_RunCommandErr cmdErr; + + cmdErr = (CRunCommand::ENUM_RunCommandErr) m_cmd.startRun(program, workDir, redirectFile, errStr); + + switch (cmdErr) { + case CRunCommand::E_RUNCMD_NO_ERROR: + break; + case CRunCommand::E_RUNCMD_CANCELLED: + return false; + break; + case CRunCommand::E_RUNCMD_FAILSTART: + return false; + break; + case CRunCommand::E_RUNCMD_ERRRUN: + return false; + break; + case CRunCommand::E_RUNCMD_CRASHED: + return false; + break; + default: + break; + } + + return true; +} + +void CGroupLoadThread::run() +{ + CConfigManager* confManager; + confManager = CConfigManager::getInstance(); + + QDir currentDir(QDir::currentPath()); + +/* + // write output to qtag config file + QFile qTagConfigFile(QTagger::kQTAG_CONFIG_FILE); + + qTagConfigFile.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream qTagConfigFileOut(&qTagConfigFile); + qTagConfigFileOut << "groupLoad=" << m_groupItem.m_name << endl; + + qTagConfigFile.close(); + + QString tagDbFileName = QString(QTagger::kQTAG_TAGS_DIR) + "/" + m_groupItem.m_name + "/" + QString(QTagger::kQTAG_DEFAULT_TAGDBNAME); + + if (m_taggerPtr != NULL) { + m_taggerPtr->loadTagList(tagDbFileName); + } +*/ + + if (m_outputItemListPtr != NULL) { + m_outputItemListPtr->clear(); + } + + QString tagRootDir = currentDir.absoluteFilePath(confManager->getAppSettingValue("TagDir").toString()); + QStringList groupProfileList; + + groupProfileList = m_groupItem.m_profileList.split(CProfileManager::kGROUP_PROFILE_SEPERATOR, QString::SkipEmptyParts); + + foreach (const QString& profileName, groupProfileList) { + QString outputFile; + int bListFileOpenResult; + + outputFile = tagRootDir + "/" + profileName + "/" + QTagger::kQTAG_DEFAULT_INPUTLIST_FILE; + + if (m_outputItemListPtr != NULL) { + bListFileOpenResult = CSourceFileList::loadFileList(outputFile, *m_outputItemListPtr); + } + } + + emit groupLoadPercentageCompleted(100); +} + + + + + + diff --git a/Model/CGroupLoadThread.h b/Model/CGroupLoadThread.h new file mode 100644 index 0000000..be16634 --- /dev/null +++ b/Model/CGroupLoadThread.h @@ -0,0 +1,46 @@ +#ifndef CGROUP_LOAD_THREAD_H +#define CGROUP_LOAD_THREAD_H + +#include +#include + +#include "Model/qTagger/qTagger.h" +#include "Model/CProfileManager.h" + +#include "Model/CGroupItem.h" +#include "Model/CRunCommand.h" +#include "Model/CConfigManager.h" + +class CGroupLoadThread: public QThread +{ + Q_OBJECT + +public: + CGroupLoadThread(QObject *parent = 0); + + void setCurrentGroupItem(const CGroupItem& groupItem); + + void setOutputItemListPtr(T_OutputItemList* outputItemListPtr); + void setTaggerPtr(QTagger* taggerPtrPtr); + + CGroupItem getCurrentGroupItem(); + + void run(); + +signals: + void groupLoadPercentageCompleted(int percentage); + +private: + bool runCommand(const QString& program, const QString& workDir, const QString& redirectFile = ""); + CGroupItem m_groupItem; + + CRunCommand m_cmd; + QTagger* m_taggerPtr; + + T_OutputItemList* m_outputItemListPtr; + +}; + +#endif // CGROUP_LOAD_THREAD_H + + diff --git a/Model/COutputItem.cpp b/Model/COutputItem.cpp new file mode 100644 index 0000000..7be357f --- /dev/null +++ b/Model/COutputItem.cpp @@ -0,0 +1,23 @@ +#include "COutputItem.h" + +COutputItem::COutputItem() +{ + m_fileId = 0; + m_fileName = ""; + m_fileLastModified = ""; + m_fileSize = 0; +} + +COutputItem::COutputItem(long fileId, const QString& fileName, const QString& fileLastModified, long fileSize) +{ + m_fileId = fileId; + + m_fileName = fileName; + m_fileLastModified = fileLastModified; + + m_fileSize = fileSize; +} + + + + diff --git a/Model/COutputItem.h b/Model/COutputItem.h new file mode 100644 index 0000000..d681de9 --- /dev/null +++ b/Model/COutputItem.h @@ -0,0 +1,27 @@ +#ifndef COUTPUT_ITEM_H +#define COUTPUT_ITEM_H + +#include +#include + +class COutputItem +{ +public: + + COutputItem(); + COutputItem(long fileId, const QString& fileName, const QString& fileLastModified, long fileSize); + + virtual ~COutputItem() {}; + + long m_fileId; + QString m_fileName; + QString m_fileLastModified; + + long m_fileSize; +}; + +#endif // COUTPUT_ITEM_H + + + + diff --git a/Model/COutputListModel.cpp b/Model/COutputListModel.cpp new file mode 100644 index 0000000..d636a6e --- /dev/null +++ b/Model/COutputListModel.cpp @@ -0,0 +1,80 @@ +#include "COutputListModel.h" + +COutputListModel::COutputListModel(QObject *parent) + : QStandardItemModel(0, 3, parent) // 3 column +{ + m_parent = static_cast (parent); + setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + setHeaderData(1, Qt::Horizontal, QObject::tr("Last Modified")); + setHeaderData(2, Qt::Horizontal, QObject::tr("Size")); + + m_outputListProxyModel = new QSortFilterProxyModel; + m_outputListProxyModel->setSourceModel(static_cast (this)); + m_outputListProxyModel->setDynamicSortFilter(true); + + m_outputListSelectionModel = new QItemSelectionModel(m_outputListProxyModel); + + qDebug() << "COutputListModel, this = " << this; +} + +void COutputListModel::clearAndResetModel() +{ + clear(); // header data will also be clear + + setColumnCount(3); // need to set back column count when QStandardItemModel clear otherwise setData will return false + + setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + setHeaderData(1, Qt::Horizontal, QObject::tr("Last Modified")); + setHeaderData(2, Qt::Horizontal, QObject::tr("Size")); +} + +QSortFilterProxyModel* COutputListModel::getProxyModel() +{ + return m_outputListProxyModel; +} + +QItemSelectionModel* COutputListModel::getSelectionModel() +{ + return m_outputListSelectionModel; +} + +void COutputListModel::addItem(const COutputItem& outputItem) +{ + quint64 fileSize; + QDateTime lastModifiedDateTime; + + insertRow(0); + + setData(index(0, 0), outputItem.m_fileName); + + setData(index(0, 0), QIcon(":/Icons/text-x-preview.ico"), Qt::DecorationRole); + + lastModifiedDateTime = QDateTime::fromString(outputItem.m_fileLastModified, "dd/MM/yyyy HH:mm:ss"); + setData(index(0, 1), lastModifiedDateTime); + + fileSize = outputItem.m_fileSize; + + setData(index(0, 2), fileSize); +} + +QVariant COutputListModel::data(const QModelIndex& index, int role) const +{ + /* YCH modified (begin) 13/03/12, no changing of color */ + /* + QColor bgColor; + + switch(role){ + case Qt::BackgroundRole: + bgColor.setNamedColor("paleturquoise"); + return QBrush(bgColor); + break; + } + */ + /* YCH modified (end) 13/03/12, no changing of color */ + + return QStandardItemModel::data(index,role); +} + + + + diff --git a/Model/COutputListModel.h b/Model/COutputListModel.h new file mode 100644 index 0000000..e76591c --- /dev/null +++ b/Model/COutputListModel.h @@ -0,0 +1,41 @@ +#ifndef COUTPUT_LIST_MODEL_H +#define COUTPUT_LIST_MODEL_H + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "Model/COutputItem.h" + +class COutputListModel: public QStandardItemModel +{ + Q_OBJECT + +public: + COutputListModel(QObject *parent = 0); + void clearAndResetModel(); + + QSortFilterProxyModel* getProxyModel(); + QItemSelectionModel* getSelectionModel(); + + void addItem(const COutputItem& outputItem); + + QVariant data(const QModelIndex& index, int role) const; + +private: + QWidget* m_parent; + + QSortFilterProxyModel* m_outputListProxyModel; + QItemSelectionModel* m_outputListSelectionModel; + +}; + +#endif // COUTPUT_LIST_MODEL_H diff --git a/Model/CProfileItem.cpp b/Model/CProfileItem.cpp new file mode 100644 index 0000000..6721e7c --- /dev/null +++ b/Model/CProfileItem.cpp @@ -0,0 +1,29 @@ +#include "CProfileItem.h" + +CProfileItem::CProfileItem() +{ + m_name = ""; + m_srcDir = ""; + m_srcMask = ""; + m_headerMask = ""; + m_tagUpdateDateTime = ""; + m_profileCreateDateTime = ""; + m_labels = ""; +} + +CProfileItem::CProfileItem(const QString& name, const QString& srcDir, const QString& srcMask, const QString& headerMask, + const QString& tagUpdateDateTime, const QString& profileCreateDateTime, const QString& labels) +{ + m_name = name; + m_srcDir = srcDir; + m_srcMask = srcMask; + m_headerMask = headerMask; + + m_tagUpdateDateTime = tagUpdateDateTime; + m_profileCreateDateTime = profileCreateDateTime; + m_labels = labels; +} + + + + diff --git a/Model/CProfileItem.h b/Model/CProfileItem.h new file mode 100644 index 0000000..d6d6cea --- /dev/null +++ b/Model/CProfileItem.h @@ -0,0 +1,34 @@ +#ifndef CPROFILE_ITEM_H +#define CPROFILE_ITEM_H + +#include +#include +#include + +class CProfileItem +{ +public: + + CProfileItem(); + + CProfileItem(const QString& name, const QString& srcDir, const QString& srcMask, const QString& headerMask, + const QString& tagUpdateDateTime, const QString& profileCreateDateTime, const QString& labels); + + QString m_name, + m_srcDir, + m_srcMask, + m_headerMask, + + m_tagUpdateDateTime, + m_profileCreateDateTime, + + m_labels; + + virtual ~CProfileItem() {}; +}; + +#endif // CPROFILE_ITEM_H + + + + diff --git a/Model/CProfileListModel.cpp b/Model/CProfileListModel.cpp new file mode 100644 index 0000000..db271b0 --- /dev/null +++ b/Model/CProfileListModel.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include "CProfileListModel.h" +#include "Display/CProfileDlg.h" + +CProfileListModel::CProfileListModel(QObject *parent) + : QStandardItemModel(0, 4, parent) +{ + m_parent = static_cast (parent); + + // view when list is empty, view with content in CMainWindow::loadProfileList() + setHeaderData(0, Qt::Horizontal, QObject::tr("Name")); + setHeaderData(1, Qt::Horizontal, QObject::tr("Tag Update Datatime")); + setHeaderData(2, Qt::Horizontal, QObject::tr("Profile Create Datetime")); + setHeaderData(3, Qt::Horizontal, QObject::tr("Labels")); +} + +void CProfileListModel::addProfileItem(const CProfileItem& profileItem) +{ + QDateTime tagUpdateDateTime, profileCreateDatetime; + + insertRow(0); + + setData(index(0, 0), profileItem.m_name); + + if (profileItem.m_tagUpdateDateTime == "") { + setData(index(0, 1), ""); + } else { + tagUpdateDateTime = QDateTime::fromString(profileItem.m_tagUpdateDateTime, "dd/MM/yyyy HH:mm:ss"); + setData(index(0, 1), tagUpdateDateTime); + } + + if (profileItem.m_profileCreateDateTime == "") { + setData(index(0, 2), ""); + } else { + profileCreateDatetime = QDateTime::fromString(profileItem.m_profileCreateDateTime, "dd/MM/yyyy HH:mm:ss"); + setData(index(0, 2), profileCreateDatetime); + } + + setData(index(0, 3), profileItem.m_labels); + +} + +bool CProfileListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + QList urlList; + + QFileInfo info; + QString fName; + + CProfileItem droppedItem; + + urlList = data->urls(); // retrieve list of urls + + foreach(QUrl url, urlList) // iterate over list + { + //qDebug("url = %s", url.toString().toLatin1().constData()); + fName = url.toLocalFile(); + //qDebug("fName = %s", fName.toLatin1().constData()); + info.setFile(fName); + + if (info.isDir()) { + + // fill default value according to item dropped + droppedItem.m_name = info.fileName(); + droppedItem.m_srcDir = fName; + droppedItem.m_srcMask = "*.cpp *.c"; + droppedItem.m_headerMask = "*.hpp *.h"; + droppedItem.m_labels = ""; + + QDialog* dialog = new CProfileDlg(droppedItem.m_name, droppedItem, m_parent); + dialog->exec(); + + } else { + QMessageBox::information(m_parent, "Add profile", "Only folder is supported!", QMessageBox::Ok); + } + } + return true; +} + +QStringList CProfileListModel::mimeTypes () const +{ + QStringList qstrList; + // list of accepted mime types accepted + qstrList.append("text/uri-list"); + return qstrList; +} + +Qt::DropActions CProfileListModel::supportedDropActions () const +{ + // actions supported + return Qt::CopyAction | Qt::MoveAction; +} + + + diff --git a/Model/CProfileListModel.h b/Model/CProfileListModel.h new file mode 100644 index 0000000..4e3dfe3 --- /dev/null +++ b/Model/CProfileListModel.h @@ -0,0 +1,25 @@ +#ifndef CPROFILE_LIST_MODEL_H +#define CPROFILE_LIST_MODEL_H + +#include +#include "Model/CProfileItem.h" + +class CProfileListModel: public QStandardItemModel +{ + Q_OBJECT + +public: + CProfileListModel(QObject *parent = 0); + + void addProfileItem(const CProfileItem& profileItem); + + bool dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent); + QStringList mimeTypes() const; + + Qt::DropActions supportedDropActions() const; + + QWidget* m_parent; +}; + +#endif // CPROFILE_LIST_MODEL_H diff --git a/Model/CProfileLoadThread.cpp b/Model/CProfileLoadThread.cpp new file mode 100644 index 0000000..18bd4c8 --- /dev/null +++ b/Model/CProfileLoadThread.cpp @@ -0,0 +1,117 @@ +#include "CProfileLoadThread.h" + +CProfileLoadThread::CProfileLoadThread(QObject *parent) + : QThread(parent) +{ + m_taggerPtr = NULL; + m_outputItemListPtr = NULL; +} + +void CProfileLoadThread::setTaggerPtr(QTagger* taggerPtr) +{ + m_taggerPtr = taggerPtr; +} + +void CProfileLoadThread::setOutputItemListPtr(T_OutputItemList* outputItemListPtr) +{ + m_outputItemListPtr = outputItemListPtr; +} + +void CProfileLoadThread::setCurrentProfileItem(const CProfileItem& profileItem) +{ + m_profileItem = profileItem; +} + +CProfileItem CProfileLoadThread::getCurrentProfileItem() +{ + return m_profileItem; +} + + +bool CProfileLoadThread::runCommand(const QString& program, const QString& workDir, const QString& redirectFile) +{ + QString errStr; + CRunCommand::ENUM_RunCommandErr cmdErr; + + cmdErr = (CRunCommand::ENUM_RunCommandErr) m_cmd.startRun(program, workDir, redirectFile, errStr); + + switch (cmdErr) { + case CRunCommand::E_RUNCMD_NO_ERROR: + break; + case CRunCommand::E_RUNCMD_CANCELLED: + return false; + break; + case CRunCommand::E_RUNCMD_FAILSTART: + return false; + break; + case CRunCommand::E_RUNCMD_ERRRUN: + return false; + break; + case CRunCommand::E_RUNCMD_CRASHED: + return false; + break; + default: + break; + } + + return true; +} + +void CProfileLoadThread::run() +{ + CConfigManager* confManager; + confManager = CConfigManager::getInstance(); + + QDir currentDir(QDir::currentPath()); + + // using absolutePath so relative and absolute path also possible + QString tagDir = currentDir.absoluteFilePath(confManager->getAppSettingValue("TagDir").toString() + "/" + m_profileItem.m_name); + + QString tagSubstDrv = confManager->getAppSettingValue("TagSubstDrv").toString(); + QString srcSubstDrv = confManager->getAppSettingValue("SrcSubstDrv").toString(); + + QString tagParam = tagSubstDrv + " " + tagDir; + QString srcParam = srcSubstDrv + " " + m_profileItem.m_srcDir; + + runCommand("subst " + tagSubstDrv + " /d", m_profileItem.m_srcDir); + runCommand("subst " + tagParam, m_profileItem.m_srcDir); + runCommand("subst " + srcSubstDrv + " /d", m_profileItem.m_srcDir); + runCommand("subst " + srcParam, m_profileItem.m_srcDir); + + // write output to qtag config file + QFile qTagConfigFile(QTagger::kQTAG_CONFIG_FILE); + + qTagConfigFile.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream qTagConfigFileOut(&qTagConfigFile); + qTagConfigFileOut << "profileLoad=" << m_profileItem.m_name << endl; + + qTagConfigFile.close(); + + QString tagDbFileName = QString(QTagger::kQTAG_TAGS_DIR) + "/" + m_profileItem.m_name + "/" + QString(QTagger::kQTAG_DEFAULT_TAGDBNAME); + + if (m_taggerPtr != NULL) { + m_taggerPtr->loadTagList(tagDbFileName); + } + + QString outputFile; + int bListFileOpenResult = -1; + + outputFile = tagDir + "/" + QTagger::kQTAG_DEFAULT_INPUTLIST_FILE; + + if (m_outputItemListPtr != NULL) { + m_outputItemListPtr->clear(); + bListFileOpenResult = CSourceFileList::loadFileList(outputFile, *m_outputItemListPtr); + } + + qDebug() << "outputFile = " << outputFile << endl; + + if (bListFileOpenResult == 0) { + emit profileLoadPercentageCompleted(100); + } else { + emit profileLoadPercentageCompleted(0); + } +} + + + + diff --git a/Model/CProfileLoadThread.h b/Model/CProfileLoadThread.h new file mode 100644 index 0000000..b7a4f64 --- /dev/null +++ b/Model/CProfileLoadThread.h @@ -0,0 +1,43 @@ +#ifndef CPROFILE_LOAD_THREAD_H +#define CPROFILE_LOAD_THREAD_H + +#include +#include + +#include "Model/qTagger/qTagger.h" + +#include "Model/CProfileItem.h" +#include "Model/CRunCommand.h" +#include "Model/CConfigManager.h" + +class CProfileLoadThread: public QThread +{ + Q_OBJECT + +public: + CProfileLoadThread(QObject *parent = 0); + + void setCurrentProfileItem(const CProfileItem& profileItem); + + void setOutputItemListPtr(T_OutputItemList* outputItemListPtr); + void setTaggerPtr(QTagger* taggerPtrPtr); + + CProfileItem getCurrentProfileItem(); + + void run(); + +signals: + void profileLoadPercentageCompleted(int percentage); + +private: + bool runCommand(const QString& program, const QString& workDir, const QString& redirectFile = ""); + CProfileItem m_profileItem; + + CRunCommand m_cmd; + QTagger* m_taggerPtr; + + T_OutputItemList* m_outputItemListPtr; + +}; + +#endif // CPROFILE_LOAD_THREAD_H diff --git a/Model/CProfileManager.cpp b/Model/CProfileManager.cpp new file mode 100644 index 0000000..96b3ee8 --- /dev/null +++ b/Model/CProfileManager.cpp @@ -0,0 +1,151 @@ +#include "CProfileManager.h" +#include "CConfigManager.h" + +#include "Utils/CUtils.h" + +CProfileManager* CProfileManager::m_manager = 0; + +const char* CProfileManager::kGROUP_PROFILE_SEPERATOR = ","; + +CProfileManager::CProfileManager() +{ + +} + +CProfileManager* CProfileManager::getInstance() +{ + if (m_manager == 0) { + m_manager = new CProfileManager(); + } + return m_manager; +} + +void CProfileManager::setProfileFile(const QString& profileFileName) +{ + m_profileFile = profileFileName; +} + +void CProfileManager::setStorageHandler(const CXmlStorageHandler& handler) +{ + m_handler = handler; +} + +void CProfileManager::attachStorage() +{ + m_handler.loadFromFile(m_profileFile, m_profileMap, m_groupMap); +} + +void CProfileManager::flushStorage() +{ + m_handler.saveToFile(m_profileFile, m_profileMap, m_groupMap); +} + +void CProfileManager::detachStorage() +{ + m_handler.saveToFile(m_profileFile, m_profileMap, m_groupMap); +} + +void CProfileManager::getProfileMap(QMap& profileMap) +{ + profileMap = m_profileMap; +} + +void CProfileManager::getGroupMap(QMap& groupMap) +{ + groupMap = m_groupMap; +} + +CProfileItem CProfileManager::getProfileItem(const QString& profileItemName) const +{ +// qDebug() << "getItem" << profileItemName << "called!\n"; +// qDebug() << "m_profileMap[profileItemName].m_name = " << m_profileMap[profileItemName].m_name << endl; +// qDebug() << "m_profileMap[profileItemName].m_srcDir = " << m_profileMap[profileItemName].m_srcDir << endl; + return m_profileMap[profileItemName]; +} + +CGroupItem CProfileManager::getGroupItem(const QString& groupItemName) const +{ + return m_groupMap[groupItemName]; +} + + +void CProfileManager::addItem(const CProfileItem& newItem) +{ + m_profileMap[newItem.m_name] = newItem; + emit profileMapUpdated(); + flushStorage(); +} + +void CProfileManager::updateProfileItem(const QString& profileItemName, const CProfileItem& newItem) +{ + QString tagDir; + + // current directory + QDir currentDir(QDir::currentPath()); + + if (profileItemName != newItem.m_name) { // profile renamed + m_profileMap.remove(profileItemName); // remove old one + + // current directory + QDir currentDir(QDir::currentPath()); + + // using absoluteFilePath so relative and absolute path also possible + tagDir = currentDir.absoluteFilePath(CConfigManager::getInstance()->getAppSettingValue("TagDir").toString() + "/" + profileItemName); + QDir dir(tagDir); + + // remove tag directory + CUtils::removeDirectory(dir); + } + + m_profileMap[newItem.m_name] = newItem; + emit profileMapUpdated(); + flushStorage(); +} + +void CProfileManager::updateGroupItem(const QString& groupItemName, const CGroupItem& newItem) +{ + if (groupItemName != newItem.m_name) { // group renamed + m_groupMap.remove(groupItemName); // remove old one + } + + m_groupMap[newItem.m_name] = newItem; + emit groupMapUpdated(); + flushStorage(); +} + + +void CProfileManager::removeProfileItem(const QString& profileItemName) +{ + QString tagDir; + + // current directory + QDir currentDir(QDir::currentPath()); + + // using absoluteFilePath so relative and absolute path also possible + tagDir = currentDir.absoluteFilePath(CConfigManager::getInstance()->getAppSettingValue("TagDir").toString() + "/" + profileItemName); + QDir dir(tagDir); + + // remove tag directory + CUtils::removeDirectory(dir); + + // remove from map + m_profileMap.remove(profileItemName); + emit profileMapUpdated(); + flushStorage(); + +} + +void CProfileManager::removeGroupItem(const QString& groupItemName) +{ + m_groupMap.remove(groupItemName); + emit groupMapUpdated(); + flushStorage(); +} + +void CProfileManager::destroy() +{ + delete m_manager; +} + + + diff --git a/Model/CProfileManager.h b/Model/CProfileManager.h new file mode 100644 index 0000000..c76a6b7 --- /dev/null +++ b/Model/CProfileManager.h @@ -0,0 +1,63 @@ +#ifndef CPROFILE_MANAGER_H +#define CPROFILE_MANAGER_H + +#include "Model/CProfileItem.h" +#include "Model/CGroupItem.h" +#include "Storage/IStorageHandler.h" +#include "Storage/CXmlStorageHandler.h" + +class CProfileManager: public QObject +{ + Q_OBJECT + +public: + virtual ~CProfileManager() {}; + + static CProfileManager* getInstance(); + + void setProfileFile(const QString& profileFileName); + void setStorageHandler(const CXmlStorageHandler& handler); + void attachStorage(); + void flushStorage(); + void detachStorage(); + + void getProfileMap(QMap& profileMap); + void getGroupMap(QMap& groupMap); + + void addItem(const CProfileItem& newItem); + + CProfileItem getProfileItem(const QString& profileItemName) const; + CGroupItem getGroupItem(const QString& groupItemName) const; + + void updateProfileItem(const QString& profileItemName, const CProfileItem& newItem); + void updateGroupItem(const QString& groupItemName, const CGroupItem& newItem); + + void removeProfileItem(const QString& profileItemName); + void removeGroupItem(const QString& groupItemName); + + void destroy(); + + static const char* kGROUP_PROFILE_SEPERATOR; + +protected: + CProfileManager(); + +signals: + void profileMapUpdated(); + void groupMapUpdated(); + +private: + CXmlStorageHandler m_handler; + + QMap m_profileMap; + QMap m_groupMap; + + QString m_profileFile; + + static CProfileManager* m_manager; + +}; + +#endif // CPROFILE_MANAGER_H + + diff --git a/Model/CProfileUpdateThread.cpp b/Model/CProfileUpdateThread.cpp new file mode 100644 index 0000000..5a81be9 --- /dev/null +++ b/Model/CProfileUpdateThread.cpp @@ -0,0 +1,326 @@ +#include "CProfileUpdateThread.h" + +CProfileUpdateThread::CProfileUpdateThread(QObject *parent) +: QThread(parent), + m_bCancelUpdate(false) +{ + +} + +void CProfileUpdateThread::setCurrentProfileItem(const CProfileItem& profileItem) +{ + m_profileItem = profileItem; +} + +void CProfileUpdateThread::setRebuildTag(bool bRebuildTag) +{ + m_bRebuildTag = bRebuildTag; +} + +void CProfileUpdateThread::initStep(int totalStep) +{ + m_stepCompleted = 0; + m_totalStep = totalStep; + + emit percentageCompleted(0); // emit 0 initially +} + +void CProfileUpdateThread::finishOneStep() +{ + int endPercent; + m_stepCompleted++; + endPercent = m_stepCompleted * (100 / m_totalStep); + emit percentageCompleted(endPercent); + + if (m_stepCompleted >= m_totalStep) { + emit percentageCompleted(100); // always 100% if finish all steps + } +} + +void CProfileUpdateThread::finishAllStep() +{ + emit percentageCompleted(100); +} + +bool CProfileUpdateThread::runCommand(const QString& program, const QString& workDir, const QString& redirectFile) +{ + QString errStr; + CRunCommand::ENUM_RunCommandErr cmdErr; + + cmdErr = (CRunCommand::ENUM_RunCommandErr) m_cmd.startRun(program, workDir, redirectFile, errStr); + + switch (cmdErr) { + case CRunCommand::E_RUNCMD_NO_ERROR: + break; + case CRunCommand::E_RUNCMD_CANCELLED: + emit cancelledTagBuild(); + return false; + break; + case CRunCommand::E_RUNCMD_FAILSTART: + emit errorDuringRun(errStr); + return false; + break; + case CRunCommand::E_RUNCMD_ERRRUN: + emit errorDuringRun(errStr); + return false; + break; + case CRunCommand::E_RUNCMD_CRASHED: + emit errorDuringRun(errStr); + return false; + break; + default: + break; + } + + finishOneStep(); // for updating progress bar + return true; +} + +void CProfileUpdateThread::cancelUpdate() +{ + m_bCancelUpdate = true; + m_cmd.cancelCommand(true); +} + +int CProfileUpdateThread::countTotalRunCmd() +{ + int i, totalCmd; + QString cmdKey, cmdStr; + + CConfigManager* confManager; + confManager = CConfigManager::getInstance(); + + totalCmd = 0; + for (i = 1; i < MAX_SUPPORTED_RUN_COMMAND+1; i++) { + cmdKey = QString("UpdateTagRunCmd") + QString::number(i); + cmdStr = confManager->getAppSettingValue(cmdKey).toString(); + + if (cmdStr.isEmpty()) { // break if no more command to run + break; + } + totalCmd = i; + } + return totalCmd; +} + +void CProfileUpdateThread::run() +{ + bool bRunResult; + + QString cmdKey, cmdStr; + QString srcTagName, targetTagName; + QString errStr; + + CConfigManager* confManager; + confManager = CConfigManager::getInstance(); + + m_bCancelUpdate = false; + + // current directory + QDir currentDir(QDir::currentPath()); + + // using absoluteFilePath so relative and absolute path also possible + QString tmpDir = currentDir.absoluteFilePath(confManager->getAppSettingValue("TmpDir").toString()); + + // using absoluteFilePath so relative and absolute path also possible + QString tagDir = currentDir.absoluteFilePath(confManager->getAppSettingValue("TagDir").toString() + "/" + m_profileItem.m_name); + QString tagName = "tags"; + + QString fileListFilename = tagDir + "/" + CSourceFileList::kFILE_LIST; + + initStep(countTotalRunCmd() + 2); // total run command + 2 (initial file list, tag update) + + if (!currentDir.exists(tagDir)) { + currentDir.mkpath(tagDir); + } + + if (!currentDir.exists(tmpDir)) { + currentDir.mkpath(tmpDir); + } + + /* first step, recursively list the source and header files to currentListFile */ + QStringList nameFilters; + QStringList srcMaskList = m_profileItem.m_srcMask.split(" "); + QStringList headerMaskList = m_profileItem.m_headerMask.split(" "); + + nameFilters = srcMaskList + headerMaskList; + + if (m_bRebuildTag) { + T_OutputItemList resultFileList; + + CSourceFileList::generateFileList(fileListFilename, m_profileItem.m_srcDir, nameFilters, resultFileList); + + finishOneStep(); // for updating progress bar + + // create tag + QTagger tagger; + + tagger.createTag(resultFileList); + + tagger.writeTagDb(tagDir + "/" + QTagger::kQTAG_DEFAULT_TAGDBNAME); + + finishOneStep(); // for updating progress bar + + if (m_bCancelUpdate) { + emit cancelledTagBuild(); + return; + } + + finishOneStep(); // for updating progress bar + } else { // update tag + + T_OutputItemList newFileList; + T_OutputItemList existingFileList; + + QMap fileIdDeletedMap; + QMap fileIdModifiedMap; + QMap fileIdCreatedMap; + + int bListFileOpenResult; + int bListFileSaveResult; + + // key: filename + QMap existingFileInfoMap; + QMap newFileInfoMap; + + // key: file id + QMap fileMapIdxByFileId; + + // key: file id + QMap assignedFileId; + + COutputItem updatedOutputItem; + + // existing file list i.e. before update tag + bListFileOpenResult = CSourceFileList::loadFileList(fileListFilename, existingFileList); + + // put the existing file list into a map + foreach (const COutputItem& outputItem, existingFileList) { + existingFileInfoMap[outputItem.m_fileName] = outputItem; + + assignedFileId[outputItem.m_fileId] = outputItem.m_fileId; // file id assigned + } + + finishOneStep(); // for updating progress bar + + // new file list, for this update tag, not save the file list to file yet as need to update file id + CSourceFileList::generateFileList(fileListFilename, m_profileItem.m_srcDir, nameFilters, newFileList, false); + + long newFileId = 0; + + // put the new file list into a map + foreach (const COutputItem& outputItem, newFileList) { + updatedOutputItem = outputItem; + + // use previous file id if file exist before + QMap::iterator it = existingFileInfoMap.find(outputItem.m_fileName); + + if (it == existingFileInfoMap.end()) { // not exist before + + if (newFileId == 0) { // assign to largest key +1 if not exist yet + QMapIterator itMap(assignedFileId); + itMap.toBack(); + itMap.previous(); + newFileId = itMap.key() + 1; + } + + updatedOutputItem.m_fileId = newFileId; + newFileId++; // the next file id will be +1 + + } else { // exist before + updatedOutputItem.m_fileId = it.value().m_fileId; // reuse previous file id for assignment + } + + newFileInfoMap[updatedOutputItem.m_fileName] = updatedOutputItem; + fileMapIdxByFileId[updatedOutputItem.m_fileId] = updatedOutputItem; + + qDebug() << "filename in newlist" << updatedOutputItem.m_fileName; + qDebug() << "fileid in newlist" << updatedOutputItem.m_fileId; + } + + bListFileSaveResult = CSourceFileList::saveFileList(fileListFilename, fileMapIdxByFileId); + + finishOneStep(); // for updating progress bar + + // deleted file, modified file + + foreach (const COutputItem& outputItem, existingFileList) { + + QMap::iterator it = newFileInfoMap.find(outputItem.m_fileName); + + if (it == newFileInfoMap.end()) { // deleted file: in existingFileList, but not in newModifyTimeMap + qDebug() << "Deleted file: " << outputItem.m_fileName; + fileIdDeletedMap[outputItem.m_fileId] = outputItem.m_fileId; + } else { + if (it.value().m_fileLastModified != outputItem.m_fileLastModified) { // modified file: check by file modification date time + qDebug() << "Modified file: " << outputItem.m_fileName; + fileIdModifiedMap[outputItem.m_fileId] = outputItem.m_fileId; + } else { + qDebug() << "Same file: " << outputItem.m_fileName; + } + + newFileInfoMap.erase(it); // remove checked item so remaining would be new files + } + } + + // new file: the remaining files + QMap::const_iterator mapIt = newFileInfoMap.constBegin(); + while (mapIt != newFileInfoMap.constEnd()) { + qDebug() << "New file: " << mapIt.key(); + fileIdCreatedMap[mapIt.value().m_fileId] = mapIt.value().m_fileId; + ++mapIt; + } + + qDebug() << "fileIdModifiedMap:" << fileIdModifiedMap; + qDebug() << "fileIdDeletedMap:" << fileIdDeletedMap; + qDebug() << "fileIdCreatedMap:" << fileIdCreatedMap; + + // update tag + QTagger tagger; + + tagger.updateTag(fileMapIdxByFileId, tagDir + "/" + QTagger::kQTAG_DEFAULT_TAGDBNAME, fileIdCreatedMap, fileIdModifiedMap, fileIdDeletedMap); + tagger.writeTagDb(tagDir + "/" + QTagger::kQTAG_DEFAULT_TAGDBNAME); + + finishOneStep(); // for updating progress bar + + if (m_bCancelUpdate) { + emit cancelledTagBuild(); + return; + } + + finishOneStep(); // for updating progress bar + } + + for (int i = 1; i < MAX_SUPPORTED_RUN_COMMAND+1; i++) { // from 1 to MAX_SUPPORTED_RUN_COMMAND + cmdKey = QString("UpdateTagRunCmd") + QString::number(i); + cmdStr = confManager->getAppSettingValue(cmdKey).toString(); + + if (cmdStr.isEmpty()) { // break if no more command to run + qDebug() << "cmdStr empty, key: " << cmdKey << "str: " << cmdStr; + break; + } else { + cmdStr.replace("$tmpList", fileListFilename); + cmdStr.replace("$tagDir", tagDir); + bRunResult = runCommand(cmdStr, m_profileItem.m_srcDir); + if (!bRunResult) { // also break if errors during run + break; + } + } + } + + // for ctag + if (bRunResult) { // only continue if runCommand without problem + srcTagName = m_profileItem.m_srcDir + "/" + tagName; + targetTagName = tagDir + "/" + tagName; + QFile::rename(srcTagName, targetTagName); + //QFile::remove(srcTagName); + finishAllStep(); // finish all step as it's the last one + } + + +} + + + + + diff --git a/Model/CProfileUpdateThread.h b/Model/CProfileUpdateThread.h new file mode 100644 index 0000000..2bc2c17 --- /dev/null +++ b/Model/CProfileUpdateThread.h @@ -0,0 +1,58 @@ +#ifndef CPROFILE_UPDATE_THREAD_H +#define CPROFILE_UPDATE_THREAD_H + +#include +#include + +#include "Utils/commonType.h" +#include "Utils/CUtils.h" +#include "Model/qTagger/qTagger.h" + +#include "Model/CProfileItem.h" +#include "Model/CRunCommand.h" +#include "Model/CConfigManager.h" +#include "Model/qTagger/CSourceFileList.h" + +class CProfileUpdateThread: public QThread +{ + Q_OBJECT + +public: + CProfileUpdateThread(QObject *parent = 0); + + void setCurrentProfileItem(const CProfileItem& profileItem); + void setRebuildTag(bool bRebuildTag); + + void run(); + void cancelUpdate(); + +signals: + void percentageCompleted(int percentage); + void cancelledTagBuild(); + void errorDuringRun(const QString& errStr); + +private: + + bool runCommand(const QString& program, const QString& workDir, const QString& redirectFile = ""); + + void initStep(int totalStep); + void finishOneStep(); + void finishAllStep(); + + int countTotalRunCmd(); + + CProfileItem m_profileItem; + + CRunCommand m_cmd; + + int m_stepCompleted; + int m_totalStep; + + bool m_bCancelUpdate; + bool m_bRebuildTag; + + static const int MAX_SUPPORTED_RUN_COMMAND = 999; + +}; + +#endif // CPROFILE_UPDATE_THREAD_H diff --git a/Model/CRunCommand.cpp b/Model/CRunCommand.cpp new file mode 100644 index 0000000..335bfda --- /dev/null +++ b/Model/CRunCommand.cpp @@ -0,0 +1,122 @@ +#include "CRunCommand.h" + +CRunCommand::CRunCommand() + : MS_EACH_TIME_SLOT_WAIT(5000) // max wait for 5 second for each time slot +{ + +} + +CRunCommand::~CRunCommand() +{ + + +} + +int CRunCommand::startRun(const QString& program, const QString& workDir, const QString& redirectFile, QString& errStr) +{ + QProcess::ProcessError processErr = QProcess::UnknownError; + bool bProcessNotRunning; + QString outputStr; + + m_bCommandCancelled = false; + + qDebug() << "startCommand IN, cmd = (" << program << ")"; + qDebug() << "workDir = " << workDir; + + QProcess extProcess; + + extProcess.setWorkingDirectory(workDir); + if (redirectFile != "") { + extProcess.setStandardOutputFile(redirectFile, QIODevice::Append); + extProcess.setStandardErrorFile(redirectFile, QIODevice::Append); + } + + extProcess.start(program); + qDebug("Waiting process to start..."); + + bProcessNotRunning = false; + + // wait the process to start + do { + if (!(extProcess.waitForStarted(MS_EACH_TIME_SLOT_WAIT))) { + processErr = extProcess.error(); + qDebug("waitForStarted(), QProcess::error(): %d", processErr); + } + + qDebug() << "process state = " << QString::number(int(extProcess.state())); + + // also break if process not running/finish running otherwise would result in busy loop + if (extProcess.state() != QProcess::Running) { + processErr = extProcess.error(); + qDebug("process state != QProcess::Running, QProcess::error(): %d", processErr); + + bProcessNotRunning = true; + break; + } + } while (((!m_bCommandCancelled) && (processErr == QProcess::Timedout)) && (extProcess.state() != QProcess::Running)); + + qDebug("Process started, now running..."); + + if (processErr == QProcess::FailedToStart) { + errStr = program + outputStr; + return E_RUNCMD_FAILSTART; + } + + if (m_bCommandCancelled) { + // kill the runnning process + if (extProcess.state() == QProcess::Running) { + extProcess.kill(); + } + return E_RUNCMD_CANCELLED; + } + if (bProcessNotRunning) { + if (extProcess.exitStatus() == QProcess::CrashExit) { + errStr = program; + return E_RUNCMD_CRASHED; + } + } + + // wait the process to finish + bProcessNotRunning = false; + do { + if (!(extProcess.waitForFinished(MS_EACH_TIME_SLOT_WAIT))) { + processErr = extProcess.error(); + qDebug("waitForFinished(), QProcess::error(): %d", processErr); + } + // also break if process not running/finish running otherwise would result in busy loop + if (extProcess.state() != QProcess::Running) { + bProcessNotRunning = true; + break; + } + } while ((!m_bCommandCancelled) && (processErr == QProcess::Timedout)); + + // User cancel, kill the runnning process + if (m_bCommandCancelled) { + if (extProcess.state() == QProcess::Running) { + extProcess.kill(); + } + + return E_RUNCMD_CANCELLED; + } + + if (bProcessNotRunning) { + if (extProcess.exitStatus() == QProcess::CrashExit) { + errStr = program; + return E_RUNCMD_CRASHED; + } + } + + qDebug() << "startCommand OUT"; + + return E_RUNCMD_NO_ERROR; +} + +int CRunCommand::cancelCommand(bool bCancel) +{ + m_bCommandCancelled = true; + return 0; +} + + + + diff --git a/Model/CRunCommand.h b/Model/CRunCommand.h new file mode 100644 index 0000000..b54ad93 --- /dev/null +++ b/Model/CRunCommand.h @@ -0,0 +1,29 @@ +#ifndef CRUN_COMMAND_H +#define CRUN_COMMAND_H + +#include +#include +#include + +class CRunCommand +{ +public: + CRunCommand(); + ~CRunCommand(); + + typedef enum {E_RUNCMD_NO_ERROR, E_RUNCMD_CANCELLED, E_RUNCMD_FAILSTART, E_RUNCMD_ERRRUN, E_RUNCMD_CRASHED} ENUM_RunCommandErr; + + int startRun(const QString& program, const QString& workDir, const QString& redirectFile, QString& errStr); + + int cancelCommand(bool bCancel); + +private: + bool m_bCommandCancelled; + + const int MS_EACH_TIME_SLOT_WAIT; + +}; + +#endif // CRUN_COMMAND_H + + diff --git a/Model/qTagger/CSourceFileList.cpp b/Model/qTagger/CSourceFileList.cpp new file mode 100644 index 0000000..387c8ed --- /dev/null +++ b/Model/qTagger/CSourceFileList.cpp @@ -0,0 +1,204 @@ +#include "CSourceFileList.h" + +const char* CSourceFileList::kFILE_LIST= "fileList.txt"; + +CSourceFileList::CSourceFileList() +{ + + +} + +CSourceFileList::~CSourceFileList() +{ + +} + +int CSourceFileList::loadFileList(const QString& fileListFilename, T_OutputItemList& resultFileList) +{ + bool bListFileOpenResult; + QFile currentListFile(fileListFilename); + COutputItem outputItem; + QString lineItem; + + bListFileOpenResult = currentListFile.open(QIODevice::ReadOnly | QIODevice::Text); + + if (!bListFileOpenResult) { + qDebug() << "Cannot open list file (" << fileListFilename << ") for reading!" << endl; + return -1; + } + + QTextStream listFileStream(¤tListFile); + + QString lastFilePath = ""; + int filePathIndex = 0; + + QString currentFileName = ""; + QString currentPath = ""; + + QString currentEntry = ""; + + if (bListFileOpenResult) { + while (!listFileStream.atEnd()) { + lineItem = listFileStream.readLine(); + lineItem = lineItem.trimmed(); + + // start, end section + outputItem.m_fileId = lineItem.section('\t', 0, 0).toLong(); + currentEntry = lineItem.section('\t', 1, 1); + + filePathIndex = currentEntry.lastIndexOf("/"); + if (filePathIndex >= 0) { // full path + outputItem.m_fileName = currentEntry; + lastFilePath = currentEntry.left(filePathIndex); // index start from 0, exclude separator + } else { + outputItem.m_fileName = lastFilePath + "/" + currentEntry; + } + + outputItem.m_fileLastModified = lineItem.section('\t', 2, 2); + outputItem.m_fileSize = lineItem.section('\t', 3, 3).toLong(); + + resultFileList << outputItem; + } + currentListFile.close(); + return 0; + } + return 0; +} + +int CSourceFileList::saveFileList(const QString& fileListFilename, const QMap& resultFileList) +{ + QFile currentListFile(fileListFilename); + + if (!currentListFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Cannot open list file (" << fileListFilename << ") for writing!" << endl; + } + + QTextStream listFileStream(¤tListFile); + + COutputItem outputItem; + + QString lastFilePath = ""; + int filePathIndex = 0; + + QString currentFileName = ""; + QString currentPath = ""; + + foreach (const COutputItem& outputItem, resultFileList) { + // file id + listFileStream << QString::number(outputItem.m_fileId); + listFileStream << "\t"; + + // filename + filePathIndex = outputItem.m_fileName.lastIndexOf(QDir::separator()); + if (filePathIndex >= 0) { + currentFileName = outputItem.m_fileName.mid(filePathIndex + 1); // exclude separator + currentPath = outputItem.m_fileName.left(filePathIndex); + + if (currentPath == lastFilePath) { + listFileStream << currentFileName; + } else { + listFileStream << currentPath; + lastFilePath = currentPath; + } + } + + listFileStream << "\t"; + + // last modified datetime + listFileStream << outputItem.m_fileLastModified; + listFileStream << "\t"; + + // file size + listFileStream << QString::number(outputItem.m_fileSize); + listFileStream << "\n"; + } + + currentListFile.flush(); + currentListFile.close(); + return 0; +} + +int CSourceFileList::generateFileList(const QString& resultFilename, const QString& srcDir, const QStringList& nameFilters, T_OutputItemList& resultFileList, bool bSaveToFile) +{ + QFile currentListFile(resultFilename); + + QTextStream listFileStream; + + if (bSaveToFile) { + if (!currentListFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Cannot open list file (" << resultFilename << ") for writing!" << endl; + } + + listFileStream.setDevice(¤tListFile); + } + + QDirIterator iter(srcDir, QDirIterator::Subdirectories|QDirIterator::FollowSymlinks); + COutputItem outputItem; + QString lastModifiedDateTime; + QString fileSizeStr; + + long fileId = 0; + + QString lastFilePath = ""; + + QString currentPath; + QString currentFileName; + + while (iter.hasNext()) { + if (QDir::match(nameFilters, iter.fileName())) { + outputItem.m_fileName = iter.filePath(); + + QFileInfo fileInfo(outputItem.m_fileName); + fileInfo.setCaching(false); + + outputItem.m_fileId = fileId; + + lastModifiedDateTime = fileInfo.lastModified().toString("dd/MM/yyyy hh:mm:ss"); + outputItem.m_fileLastModified = lastModifiedDateTime; // update outputItem last modified datetime + + outputItem.m_fileSize = fileInfo.size(); // update outputItem file size + + if (bSaveToFile) { + // file id + listFileStream << QString::number(outputItem.m_fileId); + listFileStream << "\t"; + + // filename; write filename only if same path as previous one + if (fileInfo.path() == lastFilePath) { + listFileStream << fileInfo.fileName(); + } else { + listFileStream << outputItem.m_fileName; + lastFilePath = fileInfo.path(); // update last path + } + listFileStream << "\t"; + + // last modified datetime + listFileStream << lastModifiedDateTime; + listFileStream << "\t"; + + // file size + listFileStream << QString::number(outputItem.m_fileSize); + listFileStream << "\n"; + + listFileStream.flush(); + } + + // append to result file list + resultFileList << outputItem; + + fileId++; + } + iter.next(); + } + + if (bSaveToFile) { + currentListFile.close(); + } + + return 0; +} + + + + + diff --git a/Model/qTagger/CSourceFileList.h b/Model/qTagger/CSourceFileList.h new file mode 100644 index 0000000..527f097 --- /dev/null +++ b/Model/qTagger/CSourceFileList.h @@ -0,0 +1,34 @@ +#ifndef CSOURCE_FILE_LIST_H +#define CSOURCE_FILE_LIST_H + +#include +#include +#include +#include + +#include +#include + +#include "../COutputItem.h" + +typedef QList T_OutputItemList; + +class CSourceFileList +{ +public: + CSourceFileList(); + ~CSourceFileList(); + + static int loadFileList(const QString& fileListFilename, T_OutputItemList& resultFileList); + static int saveFileList(const QString& fileListFilename, const QMap& resultFileList); + + static int generateFileList(const QString& resultFilename, const QString& srcDir, const QStringList& nameFilters, T_OutputItemList& resultFileList, bool bSaveToFile = true); + + static const char* kFILE_LIST; +}; + + + +#endif // CSOURCE_FILE_LIST_H + + diff --git a/Model/qTagger/CTagResultItem.cpp b/Model/qTagger/CTagResultItem.cpp new file mode 100644 index 0000000..a4486f1 --- /dev/null +++ b/Model/qTagger/CTagResultItem.cpp @@ -0,0 +1,26 @@ +#include "CTagResultItem.h" + +const char* CTagResultItem::kFIELD_RESULT_SEPERATOR = ":"; + +CTagResultItem::CTagResultItem() +{ + +} + +CTagResultItem::~CTagResultItem() +{ + +} + +ostream& operator<<(ostream& ost, const CTagResultItem& item) +{ + QString resultStr = (item.filePath_ + CTagResultItem::kFIELD_RESULT_SEPERATOR + QString::number(item.fileLineNum_) + CTagResultItem::kFIELD_RESULT_SEPERATOR + item.fileLineSrc_); + + ost << resultStr.toStdString(); + + return ost; +} + + + + diff --git a/Model/qTagger/CTagResultItem.h b/Model/qTagger/CTagResultItem.h new file mode 100644 index 0000000..e9af130 --- /dev/null +++ b/Model/qTagger/CTagResultItem.h @@ -0,0 +1,36 @@ +#ifndef CTAG_RESULT_ITEM_H +#define CTAG_RESULT_ITEM_H + +#include +#include + +#include +using namespace std; + +class CTagResultItem +{ +public: + CTagResultItem(); + virtual ~CTagResultItem(); + + QString filePath_; + unsigned long fileLineNum_; + QString fileLineSrc_; + + QStringList fileLineSrcBeforeList_; + int lineSrcIndentLevel_; + QStringList fileLineSrcAfterList_; + + QList beforeIndentLevelList_; + QList afterIndentLevelList_; + + QString functionSignature_; + + static const char* kFIELD_RESULT_SEPERATOR; + +}; + +ostream& operator<<(ostream& ost, const CTagResultItem& item); + +#endif // CTAG_RESULT_ITEM_H + diff --git a/Model/qTagger/qTagger.cpp b/Model/qTagger/qTagger.cpp new file mode 100644 index 0000000..022ce32 --- /dev/null +++ b/Model/qTagger/qTagger.cpp @@ -0,0 +1,954 @@ +#include "qTagger.h" + +//#define kDEBUG_QTAGGER_QUERY +//#define kDEBUG_QTAGGER_UPDATE_TAG + +const char* QTagger::kDB_FIELD_LINE_SEPERATOR = ","; +const char* QTagger::kDB_FIELD_FILE_SEPERATOR = ":"; +const char* QTagger::kDB_FIELD_FILE_RECORD_SEPERATOR = ";"; +const char* QTagger::kDB_TAG_RECORD_SEPERATOR = "#"; +const char* QTagger::kQTAG_CONFIG_FILE = "qtag.conf"; + +const char* QTagger::kQTAG_TAGS_DIR = "tags"; + +const char* QTagger::kQTAG_DEFAULT_TAGDBNAME = "tag.db"; + +const char* QTagger::kQTAG_DEFAULT_INPUTLIST_FILE = "fileList.txt"; + +QTagger::QTagger() +{ +} + +QTagger::~QTagger() +{ + +} + +int QTagger::createTag(const T_OutputItemList& inputFileList) +{ + long i; + unsigned long fileId; + + QString currentFilePath; + + loadKeywordFile(); + m_tokenMap.clear(); + + for (i = 0; i < inputFileList.size(); i++) { + currentFilePath = inputFileList.at(i).m_fileName; // index start from 0 + fileId = inputFileList.at(i).m_fileId; + + qDebug() << fileId << ":" << currentFilePath; + + parseSourceFile(fileId, currentFilePath, m_tokenMap); + } + return 0; +} + +int QTagger::updateTag(const QMap& inputFileList, const QString& tagDbFileName, const QMap& fileIdCreatedMap, const QMap& fileIdModifiedMap, const QMap& fileIdDeletedMap) +{ + loadKeywordFile(); + m_tokenMap.clear(); + + QFile tagDbFile(tagDbFileName); + if (!tagDbFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open tagDb file (" << tagDbFileName << ") for update!" << endl; + return -1; + } + + QTextStream tagDbFileStream(&tagDbFile); + QString line; + int tagFieldIndex; + + QString tagStr; + + QString resultFileRecordListStr; + QStringList resultFileRecordList; + + unsigned long fileId; + + QString updatedResultFileRecordListStr; + int fileIdFieldIndex; + + QString updatedFileRecordListStr; + + bool bDeletedTag, bModifiedTag; + + while (!tagDbFileStream.atEnd()) { + line = tagDbFileStream.readLine(); + + tagFieldIndex = line.indexOf(kDB_TAG_RECORD_SEPERATOR); + + if (tagFieldIndex != -1) { + tagStr = line.mid(0, tagFieldIndex); // length should be tagFieldIndex - 0 i.e. tagFieldIndex + + resultFileRecordListStr = line.mid(tagFieldIndex + 1); // exclude kDB_TAG_RECORD_SEPERATOR + resultFileRecordList = resultFileRecordListStr.split(kDB_FIELD_FILE_RECORD_SEPERATOR, QString::SkipEmptyParts); + + updatedFileRecordListStr = ""; + + // check each file record in a tag entry + foreach (const QString& resultFileRecord, resultFileRecordList) { + fileIdFieldIndex = resultFileRecord.indexOf(kDB_FIELD_FILE_SEPERATOR); + fileId = resultFileRecord.mid(0, fileIdFieldIndex).toULong(); + + bModifiedTag = false; + bDeletedTag = false; + + QMap::const_iterator it = fileIdModifiedMap.find(fileId); + if (it != fileIdModifiedMap.end()) { // modified tag + // modified tag, remove it from tagDb, to be added later as new tag + bModifiedTag = true; + + } else { // check whether it is a deleted tag + + QMap::const_iterator it = fileIdDeletedMap.find(fileId); + if (it != fileIdDeletedMap.end()) { // deleted tag + // deleted tag, remove it from tagDb + bDeletedTag = true; + } + } + + if (bModifiedTag || bDeletedTag) { + // removal from tagDb + } else { + updatedFileRecordListStr = updatedFileRecordListStr + kDB_FIELD_FILE_RECORD_SEPERATOR + resultFileRecord; + } + } + + if (updatedFileRecordListStr != "") { // only add to token map if there is record + m_tokenMap[tagStr] = updatedFileRecordListStr; + } + } + } + + tagDbFile.close(); + + // new file + QString currentFilePath; + +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "parseSourceFile for newFile" << endl; +#endif + + foreach (long fileIdCreated, fileIdCreatedMap) { +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "fileIdCreated =" << fileIdCreated << endl; +#endif + currentFilePath = inputFileList[fileIdCreated].m_fileName; +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "currentFilePath =" << currentFilePath << endl; +#endif + parseSourceFile(fileIdCreated, currentFilePath, m_tokenMap); + } + +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "parseSourceFile for modifiedFile" << endl; +#endif + + // modified file + foreach (long fileIdCreated, fileIdModifiedMap) { +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "fileIdCreated =" << fileIdCreated << endl; +#endif + currentFilePath = inputFileList[fileIdCreated].m_fileName; +#ifdef kDEBUG_QTAGGER_UPDATE_TAG + qDebug() << "currentFilePath =" << currentFilePath << endl; +#endif + parseSourceFile(fileIdCreated, currentFilePath, m_tokenMap); + } + + return 0; +} + +int QTagger::writeTagDb(const QString& tagDbFileName) +{ + QFile tagDbFile(tagDbFileName); + if (!tagDbFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Cannot open tagDb file (" << tagDbFileName << ") for writing!" << endl; + return -1; + } + + QTextStream tagDb(&tagDbFile); + + QList tagList = m_tokenMap.keys(); + + qDebug() << "Before writing. Tag total: " << m_tokenMap.size() << endl; + + for (int i = 0; i < tagList.size(); ++i) { + tagDb << tagList[i] << kDB_TAG_RECORD_SEPERATOR << m_tokenMap[tagList[i]] << '\n'; + } + + tagDb.flush(); + tagDbFile.close(); + + qDebug() << "Finish writing. Tag total: " << m_tokenMap.size() << endl; + + return 0; +} + +int QTagger::getFileLineContent(const QString& fileName, const QList& lineNumList, QList& resultLineList, + const QStringList& lineFilterStrList, const QStringList& functionNameFilterStrList, const QStringList& excludePatternFilterStrList, + int linePrintBeforeMatch, int linePrintAfterMatch) +{ + QFile sourceFile(fileName); + QString line; + unsigned long currentLineNum = 0; + unsigned long j; + + long k; + int i; + + int functionBracketIndex; + int closeBracketIndex; + + bool bCanSkip; + + QStringList lastLines; + QList lastManualIndentLevelList; + + QString lastLinesJoined; + + + bool bMatchedLineFilterStringList; + bool bMatchedFunctionNameFilter; + bool bPassExcludePatternFilter; + + if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open source file (" << fileName << ") for reading!" << endl; + return -1; + } + + QTextStream sourceFileStream(&sourceFile); + + j = 0; + + unsigned long lineNumListTotal = static_cast (lineNumList.size()); + + int linePrintAfter = 0; + + CTagResultItem resultItem; + + CTagResultItem pendingResultItem; + bool bGotPendingResultItem = false; + + int prevousIndentLevel = 0; + int indentLevel = 0; + + int openBracketIndex = 0; + + resetCommentSkip(); + + resultItem.functionSignature_.clear(); + + int manualIndentLevel = 0; + + while (!sourceFileStream.atEnd()) { + currentLineNum++; + line = sourceFileStream.readLine(); + + manualIndentLevel = getManualIndentLevel(line); + + if (sourceFileStream.atEnd()) { + break; + } + + bCanSkip = skipInsideCommentAndRemoveComment(line, currentLineNum); + + if (bCanSkip) { + continue; + } + + lastLines.append(line); + lastManualIndentLevelList.append(manualIndentLevel); + + // increment indent level + openBracketIndex = line.indexOf("{"); + if (openBracketIndex != -1) { + indentLevel++; + } + + if ((prevousIndentLevel == 0) && (indentLevel == 1)) { + lastLinesJoined = ""; + + for (i = lastLines.size() - 1; i >= 0; i--) { // search most recent bracket match + functionBracketIndex = lastLines.at(i).indexOf("("); + if (functionBracketIndex != -1) { + lastLinesJoined = lastLines.at(i); + lastLinesJoined.truncate(functionBracketIndex); + lastLinesJoined = lastLinesJoined.trimmed(); + break; + } + } + + QString functionName; + extractLastToken(lastLinesJoined, functionName); + + if (!m_keywordSet.isEmpty()) { + if (!m_keywordSet.contains(functionName)) { + resultItem.functionSignature_ = functionName; + } + } + } + + // decrement indent level + closeBracketIndex = line.indexOf("}"); + if (closeBracketIndex != -1) { + indentLevel--; + } + + if ((j < lineNumListTotal) || (linePrintAfter > 0)) { + if (currentLineNum == lineNumList[j]) { + + if (bGotPendingResultItem) { + resultLineList << pendingResultItem; + bGotPendingResultItem = false; + } + + // result in grep format + resultItem.filePath_ = fileName; + resultItem.fileLineNum_ = currentLineNum; + resultItem.fileLineSrc_ = line; + + // line filter, assume matched, only mismatched if any query tag not matched + bMatchedLineFilterStringList = true; + for (k = 0; k < lineFilterStrList.size(); k++) { + if (!line.contains(lineFilterStrList.at(k))) { + bMatchedLineFilterStringList = false; + break; + } + } + + // exclude pattern filter, pass if not consist excluded pattern + bPassExcludePatternFilter = true; + + for (k = 0; k < excludePatternFilterStrList.size(); k++) { + if (line.contains(excludePatternFilterStrList.at(k))) { + bPassExcludePatternFilter = false; + break; + } + } + + // function filter, assume not matched if not empty, only matched if any query function name matched + if (functionNameFilterStrList.empty()) { + bMatchedFunctionNameFilter = true; + } else { + bMatchedFunctionNameFilter = false; + + // consider as already mismatch if function signature is empty + if (resultItem.functionSignature_.isEmpty()) { + bMatchedFunctionNameFilter = false; + } else { + bMatchedFunctionNameFilter = false; + + //qDebug() << "resultItem.functionSignature_ = " << resultItem.functionSignature_ << endl; + + for (k = 0; k < functionNameFilterStrList.size(); k++) { + //qDebug() << "functionNameFilterStrList.at(k) = " << functionNameFilterStrList.at(k) << endl; + + if (resultItem.functionSignature_.contains(functionNameFilterStrList.at(k))) { + bMatchedFunctionNameFilter = true; + break; + } + } + } + } + + // valid only if all matched + if (bMatchedLineFilterStringList && bMatchedFunctionNameFilter && bPassExcludePatternFilter) { + if ((linePrintBeforeMatch > 0) && (linePrintAfterMatch > 0)) { + resultItem.lineSrcIndentLevel_ = manualIndentLevel; + + int lastLineSize = lastLines.size(); + + for (k = 1; k <= linePrintBeforeMatch; k++) { + if (lastLineSize - k - 1 >= 0) { // excluding the current line + resultItem.fileLineSrcBeforeList_.append(lastLines.at(lastLineSize - k - 1)); + resultItem.beforeIndentLevelList_.append(lastManualIndentLevelList.at(lastLineSize - k - 1)); + } + } + + pendingResultItem = resultItem; + resultItem.fileLineSrcBeforeList_.clear(); // reuse resultItem + resultItem.beforeIndentLevelList_.clear(); + + bGotPendingResultItem = true; + + linePrintAfter = linePrintAfterMatch; + + } else if (linePrintBeforeMatch > 0) { + resultItem.lineSrcIndentLevel_ = manualIndentLevel; + + int lastLineSize = lastLines.size(); + + for (k = 1; k <= linePrintBeforeMatch; k++) { + if (lastLineSize - k - 1 >= 0) { // excluding the current line + resultItem.fileLineSrcBeforeList_.append(lastLines.at(lastLineSize - k - 1)); + resultItem.beforeIndentLevelList_.append(lastManualIndentLevelList.at(lastLineSize - k - 1)); + } + } + + resultLineList << resultItem; + resultItem.fileLineSrcBeforeList_.clear(); // reuse resultItem + resultItem.beforeIndentLevelList_.clear(); + + } else if (linePrintAfterMatch > 0) { + resultItem.lineSrcIndentLevel_ = manualIndentLevel; + pendingResultItem = resultItem; + bGotPendingResultItem = true; + + linePrintAfter = linePrintAfterMatch; + } else { + resultLineList << resultItem; + } + } + + j++; + } else { + if (linePrintAfter > 0) { + pendingResultItem.fileLineSrcAfterList_.append(line); + pendingResultItem.afterIndentLevelList_.append(manualIndentLevel); + + linePrintAfter--; + + if (linePrintAfter == 0) { // finish appending line after to print + resultLineList << pendingResultItem; + bGotPendingResultItem = false; + } + } + } + } else { // already get all matched lines + break; + } + + if (lastLines.size() > 15) { + lastLines.removeFirst(); + lastManualIndentLevelList.removeFirst(); + } + + prevousIndentLevel = indentLevel; + } + + sourceFile.close(); + + return 0; +} + +int QTagger::loadTagList(const QString& tagDbFileName) +{ + QFile tagDbFile(tagDbFileName); + int tagFieldIndex; + QString line; + QString tagName; + + if (!tagDbFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open tagDb file (" << tagDbFileName << ") for reading!" << endl; + return -1; + } + + QTextStream tagDb(&tagDbFile); + m_tagList.clear(); + + while (!tagDb.atEnd()) { + line = tagDb.readLine(); + tagFieldIndex = line.indexOf(kDB_TAG_RECORD_SEPERATOR); + + if (tagFieldIndex != -1) { + tagName = line.mid(0, tagFieldIndex); + } + m_tagList.append(tagName); + } + + tagDbFile.close(); + + loadKeywordFile(); + return 0; +} + +QStringList QTagger::getTagList() +{ + return m_tagList; +} + +int QTagger::getMatchedTags(const QString& tagToQuery, QStringList& matchedTokenList, const Qt::CaseSensitivity& caseSensitivity) +{ + QString tagQueryStr = "^" + tagToQuery; + QString tagQueryMatched = ""; + QRegExp tagQueryRegEx(tagQueryStr, caseSensitivity); + + QStringList result; + foreach (const QString &tag, m_tagList) { + if (tag.contains(tagQueryRegEx)) { + matchedTokenList += tag; + } + if (matchedTokenList.size() > 20) { + break; + } + } + + return 0; +} + +int QTagger::queryTag(const QString& inputFileName, const QString& tagDbFileName, const QString& tagToQuery, + QString& tagToQueryFiltered, QList& resultList, const Qt::CaseSensitivity& caseSensitivity) +{ + if (!tagToQuery.isEmpty()) { + QStringList tagToQueryList; + QStringList lineFilterStrList; + + QStringList fileNameFilterStrList; + QStringList functionNameFilterStrList; + QStringList excludePatternFilterStrList; + QString tagToQueryStr; + + int linePrintBeforeMatch = 0; + int linePrintAfterMatch = 0; + + tagToQueryList = tagToQuery.split(" ", QString::SkipEmptyParts); + + if (tagToQueryList.size() >= 2) { + if (m_keywordSet.contains(tagToQueryList.at(0))) { // not using keyword for query, i.e. no keyword for first word + tagToQueryList.swap(0, 1); + } + } + + tagToQueryStr = tagToQueryList.takeFirst(); // take first and remove first tag for query + + int i; + + QString queryField; + + bool bStrConvertOk; + + for (i = 0; i < tagToQueryList.size(); i++) { + queryField = tagToQueryList.at(i); + + if (queryField.startsWith("/f")) { // file name filter + queryField.remove(0, 2); // remove header + if (!queryField.isEmpty()) { + fileNameFilterStrList << queryField; + } + } else if (queryField.startsWith("/t")) { // function name filter + queryField.remove(0, 2); // remove header + if (!queryField.isEmpty()) { + functionNameFilterStrList << queryField; + } + } else if (queryField.startsWith("/x")) { // exclude pattern filter + queryField.remove(0, 2); // remove header + if (!queryField.isEmpty()) { + excludePatternFilterStrList << queryField; + } + } else if (queryField.startsWith("/b")) { // number of line to print before matches + queryField.remove(0, 2); // remove header + linePrintBeforeMatch = queryField.toInt(&bStrConvertOk); + } else if (queryField.startsWith("/a")) { // number of line to print after matches + queryField.remove(0, 2); // remove header + linePrintAfterMatch = queryField.toInt(&bStrConvertOk); + } else if (queryField.startsWith("/n")) { // number of line to print before and after matches + queryField.remove(0, 2); // remove header + linePrintBeforeMatch = queryField.toInt(&bStrConvertOk); + linePrintAfterMatch = linePrintBeforeMatch; + } else { + lineFilterStrList << queryField; + } + } + + tagToQueryFiltered = tagToQueryStr; + + T_OutputItemList inputFileItemList; + + // load input file + CSourceFileList::loadFileList(inputFileName, inputFileItemList); + + // query in tag db + QFile tagDbFile(tagDbFileName); + + if (!tagDbFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open tagDb file (" << tagDbFileName << ") for reading!" << endl; + return -1; + } + + QTextStream tagDbFileStream(&tagDbFile); + + QString tagQueryStr = "^" + tagToQueryStr + kDB_TAG_RECORD_SEPERATOR + kDB_FIELD_FILE_RECORD_SEPERATOR; // tag start in column 1 + QString tagQueryMatched = ""; + + QRegExp tagQueryRegEx(tagQueryStr, caseSensitivity); + + int tagFieldIndex; + int lineFieldIndex; + + unsigned long fileId; + + QString line; + + QString queryResultFileRecordListStr; + QStringList queryResultFileRecordList; + + QString queryResultFileName; + + QString queryResultLineNumListStr; + QStringList queryResultLineNumStrList; + + QList queryResultLineNumList; + + bool bMatchedFileNameFilter; + long k; + + while (!tagDbFileStream.atEnd()) { + line = tagDbFileStream.readLine(); + + // Format: | Tag | ";" | file 1 ID | ":" | location 1 line num | "," | location 2 line num | ... | ";" | file 2 ID | ":" | location 1 line num | ... + //tagFieldIndex = line.indexOf(tagQueryRegEx); + + tagFieldIndex = tagQueryRegEx.indexIn(line, 0); + + if (tagFieldIndex != -1) { + + // Result format: ";" | file 1 ID | ":" | location 1 line num | "," | location 2 line num | ... | ";" | file 2 ID | ":" | location 1 line num | ... + + //queryResultFileRecordListStr = line.mid(tagQueryStr.length() - 1); // exlcude tag and the caret regular expression character + queryResultFileRecordListStr = line.mid(tagQueryRegEx.matchedLength() - 1); // exlcude tag and the caret regular expression character + + //qDebug() << "queryResultFileRecordListStr = " << queryResultFileRecordListStr; + + // Result format: file 1 ID | ":" | location 1 line num | "," | location 2 line num | ... + queryResultFileRecordList = queryResultFileRecordListStr.split(kDB_FIELD_FILE_RECORD_SEPERATOR, QString::SkipEmptyParts); + + foreach (const QString& queryResultFileRecord, queryResultFileRecordList) { + + lineFieldIndex = queryResultFileRecord.indexOf(kDB_FIELD_FILE_SEPERATOR); + + fileId = queryResultFileRecord.mid(0, lineFieldIndex).toULong(); + +#ifdef kDEBUG_QTAGGER_QUERY + qDebug() << "fileId = " << fileId; +#endif + + queryResultFileName = inputFileItemList[fileId].m_fileName; + +#ifdef kDEBUG_QTAGGER_QUERY + qDebug() << "queryResultFileName = " << queryResultFileName; +#endif + + // filename filter, assume not matched if not empty, only matched if any query filename matched + if (fileNameFilterStrList.empty()) { + bMatchedFileNameFilter = true; + } else { + bMatchedFileNameFilter = false; + + //qDebug() << "fileName = " << fileName << endl; + + for (k = 0; k < fileNameFilterStrList.size(); k++) { + + //qDebug() << "fileNameFilterStrList.at(k) = " << fileNameFilterStrList.at(k) << endl; + if (queryResultFileName.contains(fileNameFilterStrList.at(k))) { + bMatchedFileNameFilter = true; + break; + } + } + } + + if (!bMatchedFileNameFilter) { // skip if not match file name + continue; + } + + // Result format: location 1 line num | "," | location 2 line num | ... + queryResultLineNumListStr = queryResultFileRecord.mid(lineFieldIndex + 1); + +#ifdef kDEBUG_QTAGGER_QUERY + qDebug() << "queryResultLineNumListStr = " << queryResultLineNumListStr; +#endif + + // Result format: location 1 line num + queryResultLineNumStrList = queryResultLineNumListStr.split(kDB_FIELD_LINE_SEPERATOR, QString::SkipEmptyParts); + + queryResultLineNumList.clear(); + foreach (const QString& queryResultLineNumStr, queryResultLineNumStrList) { + queryResultLineNumList << queryResultLineNumStr.toULong(); + } + + getFileLineContent(queryResultFileName, queryResultLineNumList, resultList, + lineFilterStrList, functionNameFilterStrList, excludePatternFilterStrList, + linePrintBeforeMatch, linePrintAfterMatch); + } + } + } + tagDbFile.close(); + } + return 0; +} + +int QTagger::resetCommentSkip() +{ + bBlockCommentFollowing_ = false; + blockCommentStartIndex_ = -1; + blockCommentEndIndex_ = -1; + + blockCommentBeginCol_ = -1; + blockCommentBeginLine_ = 0; + + lineCommentStartIndex_ = -1; + commentAction_ = NON_COMMENT; + + bSkipCommentIndexCheck_ = false; + return 0; +} + +bool QTagger::skipInsideCommentAndRemoveComment(QString& currentLineRead, const unsigned long lineNumReading) +{ + currentLineRead = currentLineRead.trimmed(); + + // do not check comment start when already inside comment + if (!bBlockCommentFollowing_) { + commentAction_ = NON_COMMENT; + + lineCommentStartIndex_ = currentLineRead.indexOf("//"); + blockCommentStartIndex_ = currentLineRead.indexOf("/*"); + + // check if contains comment + if ((lineCommentStartIndex_ >= 0) && (blockCommentStartIndex_ == -1)) { // only line comment string + commentAction_ = LINE_COMMENT; + } else if ((blockCommentStartIndex_ >= 0) && (lineCommentStartIndex_ == -1)) { // only block comment string + commentAction_ = BLOCK_COMMENT; + } else if ((lineCommentStartIndex_ >= 0) && (blockCommentStartIndex_ >= 0)) { // contains both kind of comment, depends on which appears earlier + if (lineCommentStartIndex_ < blockCommentStartIndex_) { + commentAction_ = LINE_COMMENT; + } else if (blockCommentStartIndex_ < lineCommentStartIndex_) { + commentAction_ = BLOCK_COMMENT; + } + } + + if (commentAction_ == LINE_COMMENT) { + currentLineRead.remove(lineCommentStartIndex_, currentLineRead.length() - lineCommentStartIndex_); // remove from start of line comment until line end + } else if (commentAction_ == BLOCK_COMMENT) { + blockCommentBeginCol_ = blockCommentStartIndex_; + + bBlockCommentFollowing_ = true; + blockCommentBeginLine_ = lineNumReading; + } + } + + // skipping comment, as comment following + if (bBlockCommentFollowing_) { + blockCommentEndIndex_ = currentLineRead.indexOf("*/"); + + if (blockCommentEndIndex_ == -1) { // no comment end + if (blockCommentBeginLine_ == lineNumReading) { // has comment started in this line, only skip the line start with comment + currentLineRead.remove(blockCommentBeginCol_, currentLineRead.length() - blockCommentBeginCol_); + } else { + return true; // still comment, can skip + } + } else { // has comment end + if (blockCommentBeginLine_ == lineNumReading) { // comment start, end at the same line + currentLineRead.remove(blockCommentBeginCol_, blockCommentEndIndex_ - blockCommentBeginCol_ + 2); // include length of comment end string + } else { // skip comment from column 0 + currentLineRead.remove(0, blockCommentEndIndex_ - blockCommentBeginCol_ + 2); // include length of comment end string + } + + bBlockCommentFollowing_ = false; + } + } + + // after remove all comment, can skip the line if it becomes empty + if (currentLineRead.isEmpty()) { + return true; + } + + return false; +} + +int QTagger::getManualIndentLevel(QString& line) +{ + int indentLevel = 0; + int i; + int tabCount = 0; + int spaceCount = 0; + + for (i = 0; i < line.length(); i++) { + if (line.at(i) == '\t') { + tabCount++; + } else if (line.at(i) == ' ') { + spaceCount++; + } else { + break; + } + } + + indentLevel = tabCount + spaceCount / 3; + + return indentLevel; +} + + +/*** + * Parse source file and update token map + */ +bool QTagger::parseSourceFile(unsigned long fileId, const QString& fileName, T_TokenMapType& tokenMap) +{ + QFile sourcefile(fileName); + + QSet tagCurrentLineSet; // remember tag for current line, not putting tag duplicated in the same line + + if (!sourcefile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open source file (" << fileName << ") for reading in parseSourceFile()!" << endl; + return false; + } + + QTextStream sourcefileStream(&sourcefile); + + qDebug() << "parseSourceFile IN, id =" << fileId << ", fileName =" << fileName << endl; + + QStringList tokenList; + QString fileIdStr = QString::number(fileId); + + QString tokenMapValue; + QString currentLineRead; + QString lastLineStr; + + QString fileIdField; + int fileIdFieldIndex; + + unsigned long lineNumReading = 0; + bool bCanSkip; + + resetCommentSkip(); + + while (!sourcefileStream.atEnd()) { + lineNumReading++; + + tagCurrentLineSet.clear(); + + currentLineRead = sourcefileStream.readLine(); + if (sourcefileStream.atEnd()) { + break; + } + + bCanSkip = skipInsideCommentAndRemoveComment(currentLineRead, lineNumReading); + + if (bCanSkip) { + continue; + } + + tokenList.clear(); + extractWordTokens(currentLineRead, tokenList); + foreach (const QString& token, tokenList) { + if (token.length() == 1) { // not storing single character + continue; + } + + if (token.length() == 2) { + if (token.at(0).isDigit() && token.at(1).isDigit()) { // not storing two digit tag + continue; + } + } + + if (!tagCurrentLineSet.contains(token)) { // as not storing tag duplicate in same line + tagCurrentLineSet.insert(token); + + if (!m_keywordSet.contains(token)) { // not storing language keyword + + fileIdField = kDB_FIELD_FILE_RECORD_SEPERATOR + fileIdStr + kDB_FIELD_FILE_SEPERATOR; + + if (tokenMap.contains(token)) { // token already exists + + tokenMapValue = tokenMap[token]; + + // File format: ";" | file 1 ID | ":" | location 1 line num | "," | location 2 line num | ... | ";" | file 2 ID | ":" | location 1 line num | ... + + fileIdFieldIndex = tokenMapValue.lastIndexOf(fileIdField); // search from backward + + if (fileIdFieldIndex >= 0) { // already exists in the same file + + tokenMap[token] = tokenMapValue + kDB_FIELD_LINE_SEPERATOR + QString::number(lineNumReading); // append new location + } else { + tokenMap[token] = tokenMapValue + fileIdField + QString::number(lineNumReading); + } + } else { // new entry + tokenMap[token] = fileIdField + QString::number(lineNumReading); + } + } + } + } + } + sourcefile.close(); + + return true; +} + +void QTagger::extractWordTokens(const QString& str, QStringList& tokenList) +{ + int i; + + QString currentWord = ""; + unsigned char currentChar; + bool bContinueScanning = false; + + for (i = 0; i < str.length(); i++) { + bContinueScanning = false; + currentChar = (unsigned char) (str.at(i). toLatin1()); + if (((currentChar >= 'a') && (currentChar <= 'z')) // small capital + || ((currentChar >= 'A') && (currentChar <= 'Z')) // large capital + || ((currentChar >= '0') && (currentChar <= '9')) // Number + || (currentChar == '_')) { // undercore + currentWord += currentChar; + bContinueScanning = true; + } + + if (!bContinueScanning || (i == (str.length() - 1))) { // encounter seperator or line end + if (!currentWord.isEmpty()) { + tokenList << currentWord; + currentWord = ""; + } + } + } +} + +void QTagger::extractLastToken(const QString& str, QString& lastToken) +{ + int i; + + QString currentWord = ""; + unsigned char currentChar; + + for (i = str.length()-1; i >= 0 ; i--) { // search from the end of string + currentChar = (unsigned char) (str.at(i).toLatin1()); + if (((currentChar >= 'a') && (currentChar <= 'z')) // small capital + || ((currentChar >= 'A') && (currentChar <= 'Z')) // large capital + || ((currentChar >= '0') && (currentChar <= '9')) // Number + || (currentChar == ':') + || (currentChar == '_')) { // undercore + currentWord = currentChar + currentWord; // add char to the beginning + } else { + break; + } + } + lastToken = currentWord; +} + +void QTagger::loadKeywordFile() +{ + QString keywordFileName = QCoreApplication::applicationDirPath() + "/keyword.txt"; + QFile file(keywordFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "cannot open keyword file (" << keywordFileName << ") for reading!" << endl; + return; + } + + QTextStream inputFileStream(&file); + + m_keywordSet.clear(); + while (!inputFileStream.atEnd()) { + QString line = inputFileStream.readLine(); + QStringList keywordList = line.split(" ", QString::SkipEmptyParts); + + foreach (const QString& keyword, keywordList) { + m_keywordSet.insert(keyword); + } + } + file.close(); +} + + + + diff --git a/Model/qTagger/qTagger.h b/Model/qTagger/qTagger.h new file mode 100644 index 0000000..c1e3605 --- /dev/null +++ b/Model/qTagger/qTagger.h @@ -0,0 +1,97 @@ +#ifndef QTAGGER_H +#define QTAGGER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "commonType.h" +#include "CUtils.h" +#include "CTagResultItem.h" + +#include "CSourceFileList.h" + +typedef QMap T_TokenMapType; + +class QTagger +{ +public: + QTagger(); + virtual ~QTagger(); + + int createTag(const T_OutputItemList& inputFileList); + int updateTag(const QMap& inputFileList, const QString& tagDbFileName, + const QMap& fileIdCreatedMap, const QMap& fileIdModifiedMap, const QMap& fileIdDeletedMap); + + int writeTagDb(const QString& tagDbFileName); + + int loadTagList(const QString& tagDbFileName); + QStringList getTagList(); + int getMatchedTags(const QString& tagToQuery, QStringList& matchedTokenList, const Qt::CaseSensitivity& caseSensitivity); + + int queryTag(const QString& inputFileName, const QString& tagDbFileName, const QString& tagToQuery, + QString& tagToQueryFiltered, QList& resultList, const Qt::CaseSensitivity& caseSensitivity); + + int resetCommentSkip(); + bool skipInsideCommentAndRemoveComment(QString& currentLineRead, const unsigned long lineNumReading); + + int getManualIndentLevel(QString& line); + + static const char* kQTAG_CONFIG_FILE; + static const char* kDB_FIELD_LINE_SEPERATOR; + static const char* kDB_FIELD_FILE_SEPERATOR; + static const char* kDB_FIELD_FILE_RECORD_SEPERATOR; + static const char* kDB_TAG_RECORD_SEPERATOR; + + static const char* kDB_FIELD_RESULT_SEPERATOR; + + static const char* kQTAG_TAGS_DIR; + + static const char* kQTAG_DEFAULT_TAGDBNAME; + + static const char* kQTAG_DEFAULT_INPUTLIST_FILE; + +private: + bool parseSourceFile(unsigned long fileId, const QString& fileName, T_TokenMapType& tokenMap); + + void extractWordTokens(const QString& str, QStringList& tokenList); + void extractLastToken(const QString& str, QString& lastToken); + + void loadKeywordFile(); + + QSet m_keywordSet; + + QStringList m_tagList; + + T_TokenMapType m_tokenMap; + + int getFileLineContent(const QString& fileName, const QList& lineNumList, QList& resultLineList, + const QStringList& lineFilterStrList, const QStringList& functionNameFilterStrList, const QStringList& excludePatternFilterStrList, + int linePrintBeforeMatch, int linePrintAfterMatch); + + typedef enum {NON_COMMENT, LINE_COMMENT, BLOCK_COMMENT} ENUM_CommentAction; + + // for comment handling + bool bBlockCommentFollowing_; + int blockCommentStartIndex_; + int blockCommentEndIndex_; + + int blockCommentBeginCol_; + unsigned long blockCommentBeginLine_; + + int lineCommentStartIndex_; + ENUM_CommentAction commentAction_; + + bool bSkipCommentIndexCheck_; + + + +}; + +#endif + diff --git a/README.md b/README.md index 86a1715..7ba6d82 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,125 @@ -# blink -Instant code search, source files locator. Index management for multiple projects. +![Blink logo](https://raw.githubusercontent.com/ychclone/blink/master/Resources/Images/graphics3.png) + +# Blink code search +Instant code search, source files locator. +Index management for multiple projects. + +[![Build status](https://ci.appveyor.com/api/projects/status/afn8q3ai3e7wphrf?svg=true)](https://ci.appveyor.com/project/ychclone/blink) + +# Screenshots +![Screencast](https://raw.githubusercontent.com/ychclone/blink/master/Screencast/Usage.gif) + +# Features +* Search without delay using prebuilt index, comparing to ack or ripgrep +* Very small index size compared to trigram +* Queries support autocomplete +* Switch multiple projects easily with individual index +* Support drag and drop for filename +* Cross platform and requires no installation + +# Download, Install + +Windows and Linux binaries are available at +https://github.com/ychclone/blink/releases + +# File listing +![File listing](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/blink_filelisting.png) + +# Code search +![Code search](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/blink_codesearch.png) + +# Usage + +1. Drop the folder (e.g. from file explorer, nautilus) into the window below +profile tab. +![Drop folder](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/usage_drop_folder.png) +2. A new profile dialog will appears. Type the file extensions that you want to index. +![New profile](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/usage_new_profile.png) +3. Right click on the profile name +4. Click "Rebuild Symbol" +5. Double click the profile name to make it the active project. +Or right click and select "Load" +6. Start file filtering and code search on the file and symbol tab + +# Configuration + +The text editor when double clicking the filename in file tab +could be set in configuration. The filename could be dropped to +other editor. +Option->Setting->Main->Default Editor + +# Compilation (Linux) + +1. Download Qt Open Source offline installer: +https://www.qt.io/offline-installers + +2. Install Qt +3. qmake +4. make +5. +``` +cp ./blink build/ +cd build +./blink +``` + +# AppImage + +1. Download linuxdeployqt-7-x86_64.AppImage: +https://github.com/probonopd/linuxdeployqt/releases + +2. chmod u+x linuxdeployqt-7-x86_64.AppImage +3. ./linuxdeployqt-7-x86_64.AppImage blinkAppImage/usr/share/applications/blink.desktop -verbose=2 -appimage + +# Tips + +## Display result lines before and after +In the text field for symbol, "/n3" could be used to display 3 lines before and after +![Multiple lines](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/blink_multiple_lines.png) + +## Match for multiple symbol +Multiple symbols (and condition) could be input for symbol queries. +e.g. Multiple match are input "CMainWindow", "_on" as queries. +![Multiple symbols](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/blink_multiple_symbols.png) + +## Show multiple project +Regular expression could be used to filter the project name and source filename name. +e.g. "Or" condition for project name using the pipe "|" regular expression. +![Regular expression](https://raw.githubusercontent.com/ychclone/blink/master/Screenshot/blink_regular_expression.png) + +# Troubleshooting + +## /usr/bin/ld: cannot find -lGL; collect2: error: ld returned 1 exit status +Sol: sudo apt install libgl1-mesa-dev + +## Qt version not match +``` +sudo rm /usr/bin/qmake +sudo ln -s /home/ychclone/Qt5.13.2/5.13.2/gcc_64/bin/qmake /usr/bin/qmake +``` + +## Segmentation fault (core dumped) when start +Please cp ./blink to build directory. +Please make sure the following config files existed in build directory: +- blink.ini +- qtag.conf +- qt.conf +- record.xml + +## qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in "" +Error message: This application failed to start because no Qt platform plugin +could be initialized. Reinstalling the application may fix this problem. + +Sol: +``` +export QT_QPA_PLATFORM_PLUGIN_PATH=/home/ychclone/Qt5.13.2/5.13.2/gcc_64/plugins/platforms +``` + + + + + + + + + diff --git a/Resources/Forms/aboutDialog.ui b/Resources/Forms/aboutDialog.ui new file mode 100644 index 0000000..4c2e6d8 --- /dev/null +++ b/Resources/Forms/aboutDialog.ui @@ -0,0 +1,107 @@ + + + aboutDialog + + + + 0 + 0 + 438 + 215 + + + + + 0 + 0 + + + + + 369 + 157 + + + + Qt::DefaultContextMenu + + + About + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + false + + + background-color: rgb(255, 255, 255); + + + + + + + + 180 + 50 + 221 + 131 + + + + + 18 + + + + Blink V1.4 +(C) ychclone 2020 + + + + + + 40 + 80 + 91 + 81 + + + + + + + :/Images/graphics3.png + + + true + + + Qt::AlignCenter + + + false + + + + + + + + + + + diff --git a/Resources/Forms/configDialog.ui b/Resources/Forms/configDialog.ui new file mode 100644 index 0000000..6b9a18e --- /dev/null +++ b/Resources/Forms/configDialog.ui @@ -0,0 +1,478 @@ + + + configDialog + + + + 0 + 0 + 773 + 537 + + + + Setting [*] + + + QPushButton:hover:flat { border: 1px solid grey; border-radius: 3px} + + + + 8 + + + 5 + + + 8 + + + 8 + + + + + 0 + + + + + 0 + + + + + 0 + 0 + + + + + + + + 0 + 0 + + + + Main + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 40 + + + + + + + + + + ... + + + true + + + + + + + + + + Default Editor: + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Display + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 40 + + + + + + + + + + ... + + + true + + + + + + + + + + Font (Profile, File): + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + 0 + 0 + + + + Advanced + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + 9 + + + 9 + + + + + QLayout::SetDefaultConstraint + + + QFormLayout::AllNonFixedFieldsGrow + + + 25 + + + + + Tag directory: + + + + + + + + + + + + ... + + + true + + + + + + + + + Source subst drive: + + + + + + + + + + Tag subst drive: + + + + + + + + + + Temp directory: + + + + + + + + + + + + ... + + + true + + + + + + + + + External Program Timeout: + + + + + + + + + + + + + + + + + + + + + OK + + + + :/Icons/22x22/gtk-ok.png:/Icons/22x22/gtk-ok.png + + + true + + + + + + + Cancel + + + + :/Icons/22x22/gtk-cancel.png:/Icons/22x22/gtk-cancel.png + + + true + + + + + + + false + + + Apply + + + true + + + + + + + + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + false + + + + 40 + 40 + + + + Qt::ElideLeft + + + QListView::Static + + + QListView::LeftToRight + + + true + + + QListView::SinglePass + + + + 100 + 100 + + + + QListView::IconMode + + + false + + + false + + + false + + + Qt::AlignHCenter + + + + Main + + + + 18 + + + + AlignCenter + + + + :/Icons/48x48/applications-system.png:/Icons/48x48/applications-system.png + + + + + Display + + + + 18 + + + + AlignCenter + + + + :/Icons/48x48/applications-graphics-5.png:/Icons/48x48/applications-graphics-5.png + + + + + Advanced + + + + 18 + + + + AlignCenter + + + + :/Icons/48x48/application-x-gnome-saved-search.png:/Icons/48x48/application-x-gnome-saved-search.png + + + + + + + + + + + diff --git a/Resources/Forms/groupDialog.ui b/Resources/Forms/groupDialog.ui new file mode 100644 index 0000000..181e0d8 --- /dev/null +++ b/Resources/Forms/groupDialog.ui @@ -0,0 +1,305 @@ + + + groupDialog + + + + 0 + 0 + 614 + 682 + + + + Group [*] + + + QPushButton:hover:flat { border: 1px solid grey; border-radius: 3px} + + + + + + 6 + + + 0 + + + + + Group + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + 15 + + + 0 + + + + + Group &name: + + + groupName_lineEdit + + + + + + + + + + &Profile list: + + + includedProfile_listWidget + + + + + + + + + QAbstractItemView::ExtendedSelection + + + true + + + + + + + + + &Labels: + + + labels_lineEdit + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + - + + + + :/Icons/22x22/edit-remove-3.png:/Icons/22x22/edit-remove-3.png + + + + 22 + 22 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + + + + + + :/Icons/22x22/edit-add-4.png:/Icons/22x22/edit-add-4.png + + + + 22 + 22 + + + + true + + + + + + + QAbstractItemView::ExtendedSelection + + + true + + + + + + + + + + + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + OK + + + + :/Icons/22x22/gtk-ok.png:/Icons/22x22/gtk-ok.png + + + true + + + + + + + Cancel + + + + :/Icons/22x22/gtk-cancel.png:/Icons/22x22/gtk-cancel.png + + + true + + + + + + + false + + + Apply + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + allGroup_comboBox + groupName_lineEdit + allProfile_listWidget + addProfile_toolButton + removeProfile_toolButton + includedProfile_listWidget + labels_lineEdit + okButton + cancelButton + applyButton + + + + + + diff --git a/Resources/Forms/mainWindow.ui b/Resources/Forms/mainWindow.ui new file mode 100644 index 0000000..599822c --- /dev/null +++ b/Resources/Forms/mainWindow.ui @@ -0,0 +1,1198 @@ + + + YCH + mainWindow + + + + 0 + 0 + 783 + 550 + + + + Blink + + + QPushButton:hover:flat { border: 1px solid grey; border-radius: 3px} +QTreeView {selection-background-color:steelblue} +QListWidget {selection-background-color:steelblue} + +QMenuBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f2f6f8, stop:0.4 #d9dee7, stop:0.6 #d0d7e2, stop: 1 #e4ecf6); + border: 1px solid lightgrey; +} + +QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, + stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); + border: 1px solid #C4C4C3; + padding: 5px; + min-width: 8ex; +} + +QTabBar::tab:selected, QTabBar::tab:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #fafafa, stop: 0.4 #f4f4f4, + stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); + padding: 5px; + padding-left: 8px; + padding-right: 8px; + border-bottom: 0px +} + +QTabBar::tab:!selected { + margin-top: 2px; + padding: 5px; + padding-left: 8px; + padding-right: 8px; +} + +QSplitter::handle { + background: ghostwhite; +} + + + + + + 1 + 1 + + + + .QWidget {background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f6f9fe, stop:0.05 #e1eaf9, stop:0.5 #d9dee7 , stop:0.8 #b6c1d0, stop: 1 #e1eaf9);} + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 1 + 1 + + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + QFrame::Plain + + + 0 + + + Qt::Horizontal + + + true + + + false + + + + + 1 + 1 + + + + + 18 + + + + + + + 0 + + + + 22 + 22 + + + + false + + + false + + + true + + + + + :/Images/profile.png:/Images/profile.png + + + Profile + + + + 2 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + Ubuntu + 16 + 50 + false + + + + Qt::WheelFocus + + + QTreeView::item {color: #0066FF;} +QTreeView::item:selected +{ +color: white; +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #97C0FC, stop: 1 #70A9FF); +} + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + + + + + 6 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 0 + 0 + + + + + 18 + + + + + + + + + + + + :/Images/group.png:/Images/group.png + + + Group + + + + 2 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + PMingLiU + 10 + + + + QTreeView::item {color: #0066FF; +background-color:qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 white, stop: 1 #FAFAFA) +} +QTreeView::item:selected +{ +color: white; +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #97C0FC, stop: 1 #70A9FF); +} + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + + + + + + + + + + + + + + + 10 + 1 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 18 + + + + + + + + + + Qt::ImhNone + + + 1 + + + + 22 + 22 + + + + true + + + + + :/Images/file.png:/Images/file.png + + + File + + + + 2 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + Ubuntu + 16 + 50 + false + + + + Qt::WheelFocus + + + QTreeView::item {color: #0066FF;} +QTreeView::item:selected +{ +color: white; +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #97C0FC, stop: 1 #70A9FF); +} + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + + + + + + 20 + 21 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 80 + 0 + + + + + 18 + + + + + + + + + + + + + + + :/Images/symbol.png:/Images/symbol.png + + + Symbol + + + + 2 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 18 + + + + + + + + true + + + QFrame {color: #0066FF; +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e6f0fc, stop: 1 #cee1ff); +} + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Previous + + + true + + + + + + + + 0 + 0 + + + + Search + + + Search + + + Next + + + Return + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 18 + + + + + + + + + + + 6 + + + 12 + + + + + + 0 + 0 + + + + Search + + + Search + + + Search + + + + :/Icons/22x22/zoom-3.png:/Icons/22x22/zoom-3.png + + + + 22 + 22 + + + + Return + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 18 + + + + + + + + + + + + + + + + + + + + 0 + 0 + 783 + 42 + + + + + &Help + + + + + + &Options + + + + + + + + + &Profile + + + + + + + + + + + + &View + + + + + + + + + + Group + + + + + + + + + + + + + + + + + toolBar + + + + + + + 20 + 20 + + + + Qt::ToolButtonIconOnly + + + TopToolBarArea + + + false + + + + + + + + + + + :/Icons/22x22/gtk-about.png:/Icons/22x22/gtk-about.png + + + &About + + + + + &Quit + + + + + true + + + + :/Icons/22x22/gtk-execute.png:/Icons/22x22/gtk-execute.png + + + &Setting + + + + + + :/Icons/22x22/gtk-new.png:/Icons/22x22/gtk-new.png + + + &New + + + + + + :/Icons/22x22/gtk-redo-ltr.png:/Icons/22x22/gtk-redo-ltr.png + + + &Load + + + + + + :/Icons/22x22/gtk-refresh.png:/Icons/22x22/gtk-refresh.png + + + &Update Symbol + + + Update Symbol + + + + + + :/Icons/22x22/gtk-properties.png:/Icons/22x22/gtk-properties.png + + + &Modify + + + + + + :/Icons/22x22/gtk-delete.png:/Icons/22x22/gtk-delete.png + + + &Delete + + + + + + :/Icons/22x22/edit-copy-4.png:/Icons/22x22/edit-copy-4.png + + + Copy Pathnames + + + Qt::WindowShortcut + + + + + + :/Icons/22x22/zoom-3.png:/Icons/22x22/zoom-3.png + + + Search + + + Search + + + Qt::WindowShortcut + + + + + + :/Icons/22x22/actions/gtk-cancel.png:/Icons/22x22/actions/gtk-cancel.png + + + Cancel update + + + + + true + + + Regular exp. + + + QAction::TextHeuristicRole + + + + + true + + + Wildcard + + + + + true + + + Fixed string + + + + + true + + + Always On Top + + + + + true + + + Transparent + + + + + true + + + Auto Hide Menu + + + + + true + + + Toolbar + + + + + true + + + Profile Panel + + + + + true + + + File Panel + + + + + actionWebZoomIn + + + Zoom In + + + + + actionWebZoomOut + + + Zoom Out + + + + + + :/Icons/22x22/document-open-folder.png:/Icons/22x22/document-open-folder.png + + + Explore + + + Explore + + + Qt::ApplicationShortcut + + + + + + :/Icons/22x22/xconsole-2.png:/Icons/22x22/xconsole-2.png + + + Console + + + Qt::ApplicationShortcut + + + + + + :/Icons/22x22/document-open-folder.png:/Icons/22x22/document-open-folder.png + + + Explore + + + + + + :/Icons/22x22/xconsole-2.png:/Icons/22x22/xconsole-2.png + + + Console + + + + + Properties + + + + + + :/Icons/22x22/edit-4.png:/Icons/22x22/edit-4.png + + + &Edit + + + + 75 + true + + + + + + true + + + Profile, Group Case Sensitive + + + + + true + + + true + + + Symbol Case Sensitive + + + + + true + + + File Case Sensitive + + + + + nextSymbolSearch + + + + + previousSymbolSearch + + + + + New + + + + + Load + + + + + Update + + + + + Modify + + + + + Delete + + + + + + :/Icons/22x22/insert-link-2.png:/Icons/22x22/insert-link-2.png + + + Add to group + + + + + + :/Icons/22x22/gtk-refresh.png:/Icons/22x22/gtk-refresh.png + + + Rebuild Symbol + + + + + + CProfileListWidget + QTreeView +
Display/CProfileListWidget.h
+
+ + COutputListWidget + QTreeView +
Display/COutputListWidget.h
+
+ + CGroupListWidget + QTreeView +
Display/CGroupListWidget.h
+
+
+ + mainTabWidget + profile_listView + profilePattern_lineEdit + infoTabWidget + group_listView + output_listView + filePattern_lineEdit + + + + + + +
diff --git a/Resources/Forms/profileDialog.ui b/Resources/Forms/profileDialog.ui new file mode 100644 index 0000000..92641f5 --- /dev/null +++ b/Resources/Forms/profileDialog.ui @@ -0,0 +1,331 @@ + + + profileDialog + + + + 0 + 0 + 729 + 468 + + + + + 1 + 1 + + + + Qt::DefaultContextMenu + + + Profile [*] + + + QPushButton:hover:flat { border: 1px solid grey; border-radius: 3px} + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 18 + + + + Profile + + + + + + 6 + + + 15 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 18 + + + + Profile &name: + + + profileName_lineEdit + + + + + + + + 18 + + + + + + + + + 18 + + + + Source &directory: + + + srcDir_lineEdit + + + + + + + + 18 + + + + &Header file mask: + + + headerfileMask_lineEdit + + + + + + + + 18 + + + + + + + + + 18 + + + + &Source file mask: + + + srcFileMask_lineEdit + + + + + + + + 18 + + + + + + + + + + + 18 + + + + + + + + ... + + + true + + + + + + + + + + 18 + + + + + + + + + 18 + + + + &Labels: + + + labels_lineEdit + + + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 18 + + + + OK + + + + :/Icons/22x22/gtk-ok.png:/Icons/22x22/gtk-ok.png + + + true + + + + + + + + 18 + + + + Cancel + + + + :/Icons/22x22/gtk-cancel.png:/Icons/22x22/gtk-cancel.png + + + true + + + + + + + false + + + + 18 + + + + Apply + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + profileName_lineEdit + headerfileMask_lineEdit + srcFileMask_lineEdit + + + + + + + diff --git a/Resources/Icons/22x22/code-class.png b/Resources/Icons/22x22/code-class.png new file mode 100644 index 0000000..60ba6cf Binary files /dev/null and b/Resources/Icons/22x22/code-class.png differ diff --git a/Resources/Icons/22x22/document-new-4.png b/Resources/Icons/22x22/document-new-4.png new file mode 100644 index 0000000..59c1dbd Binary files /dev/null and b/Resources/Icons/22x22/document-new-4.png differ diff --git a/Resources/Icons/22x22/document-open-6.png b/Resources/Icons/22x22/document-open-6.png new file mode 100644 index 0000000..616f45f Binary files /dev/null and b/Resources/Icons/22x22/document-open-6.png differ diff --git a/Resources/Icons/22x22/document-open-folder.png b/Resources/Icons/22x22/document-open-folder.png new file mode 100644 index 0000000..cb49a03 Binary files /dev/null and b/Resources/Icons/22x22/document-open-folder.png differ diff --git a/Resources/Icons/22x22/edit-4.png b/Resources/Icons/22x22/edit-4.png new file mode 100644 index 0000000..e6634c0 Binary files /dev/null and b/Resources/Icons/22x22/edit-4.png differ diff --git a/Resources/Icons/22x22/edit-add-4.png b/Resources/Icons/22x22/edit-add-4.png new file mode 100644 index 0000000..7c098b6 Binary files /dev/null and b/Resources/Icons/22x22/edit-add-4.png differ diff --git a/Resources/Icons/22x22/edit-copy-4.png b/Resources/Icons/22x22/edit-copy-4.png new file mode 100644 index 0000000..b3a0119 Binary files /dev/null and b/Resources/Icons/22x22/edit-copy-4.png differ diff --git a/Resources/Icons/22x22/edit-remove-3.png b/Resources/Icons/22x22/edit-remove-3.png new file mode 100644 index 0000000..a494f4c Binary files /dev/null and b/Resources/Icons/22x22/edit-remove-3.png differ diff --git a/Resources/Icons/22x22/gtk-about.png b/Resources/Icons/22x22/gtk-about.png new file mode 100644 index 0000000..90ce540 Binary files /dev/null and b/Resources/Icons/22x22/gtk-about.png differ diff --git a/Resources/Icons/22x22/gtk-cancel.png b/Resources/Icons/22x22/gtk-cancel.png new file mode 100644 index 0000000..5cb3841 Binary files /dev/null and b/Resources/Icons/22x22/gtk-cancel.png differ diff --git a/Resources/Icons/22x22/gtk-delete.png b/Resources/Icons/22x22/gtk-delete.png new file mode 100644 index 0000000..0ac3589 Binary files /dev/null and b/Resources/Icons/22x22/gtk-delete.png differ diff --git a/Resources/Icons/22x22/gtk-execute.png b/Resources/Icons/22x22/gtk-execute.png new file mode 100644 index 0000000..7fdb6f5 Binary files /dev/null and b/Resources/Icons/22x22/gtk-execute.png differ diff --git a/Resources/Icons/22x22/gtk-new.png b/Resources/Icons/22x22/gtk-new.png new file mode 100644 index 0000000..7274a21 Binary files /dev/null and b/Resources/Icons/22x22/gtk-new.png differ diff --git a/Resources/Icons/22x22/gtk-ok.png b/Resources/Icons/22x22/gtk-ok.png new file mode 100644 index 0000000..450a80c Binary files /dev/null and b/Resources/Icons/22x22/gtk-ok.png differ diff --git a/Resources/Icons/22x22/gtk-properties.png b/Resources/Icons/22x22/gtk-properties.png new file mode 100644 index 0000000..08ba326 Binary files /dev/null and b/Resources/Icons/22x22/gtk-properties.png differ diff --git a/Resources/Icons/22x22/gtk-redo-ltr.png b/Resources/Icons/22x22/gtk-redo-ltr.png new file mode 100644 index 0000000..712a8ee Binary files /dev/null and b/Resources/Icons/22x22/gtk-redo-ltr.png differ diff --git a/Resources/Icons/22x22/gtk-refresh.png b/Resources/Icons/22x22/gtk-refresh.png new file mode 100644 index 0000000..952b5f7 Binary files /dev/null and b/Resources/Icons/22x22/gtk-refresh.png differ diff --git a/Resources/Icons/22x22/insert-link-2.png b/Resources/Icons/22x22/insert-link-2.png new file mode 100644 index 0000000..aad767b Binary files /dev/null and b/Resources/Icons/22x22/insert-link-2.png differ diff --git a/Resources/Icons/22x22/view-process-all.png b/Resources/Icons/22x22/view-process-all.png new file mode 100644 index 0000000..09211c2 Binary files /dev/null and b/Resources/Icons/22x22/view-process-all.png differ diff --git a/Resources/Icons/22x22/xconsole-2.png b/Resources/Icons/22x22/xconsole-2.png new file mode 100644 index 0000000..a25da18 Binary files /dev/null and b/Resources/Icons/22x22/xconsole-2.png differ diff --git a/Resources/Icons/22x22/zoom-3.png b/Resources/Icons/22x22/zoom-3.png new file mode 100644 index 0000000..2807876 Binary files /dev/null and b/Resources/Icons/22x22/zoom-3.png differ diff --git a/Resources/Icons/48x48/application-x-gnome-saved-search.png b/Resources/Icons/48x48/application-x-gnome-saved-search.png new file mode 100644 index 0000000..b3c9fad Binary files /dev/null and b/Resources/Icons/48x48/application-x-gnome-saved-search.png differ diff --git a/Resources/Icons/48x48/applications-graphics-5.png b/Resources/Icons/48x48/applications-graphics-5.png new file mode 100644 index 0000000..26d67cd Binary files /dev/null and b/Resources/Icons/48x48/applications-graphics-5.png differ diff --git a/Resources/Icons/48x48/applications-system.png b/Resources/Icons/48x48/applications-system.png new file mode 100644 index 0000000..d8e2f5e Binary files /dev/null and b/Resources/Icons/48x48/applications-system.png differ diff --git a/Resources/Icons/48x48/forward.png b/Resources/Icons/48x48/forward.png new file mode 100644 index 0000000..1f9a697 Binary files /dev/null and b/Resources/Icons/48x48/forward.png differ diff --git a/Resources/Icons/appIcons.rc b/Resources/Icons/appIcons.rc new file mode 100644 index 0000000..3c07bea --- /dev/null +++ b/Resources/Icons/appIcons.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE graphics3.ico diff --git a/Resources/Icons/graphics.ico b/Resources/Icons/graphics.ico new file mode 100644 index 0000000..8455047 Binary files /dev/null and b/Resources/Icons/graphics.ico differ diff --git a/Resources/Icons/graphics2.ico b/Resources/Icons/graphics2.ico new file mode 100644 index 0000000..cc6c4e1 Binary files /dev/null and b/Resources/Icons/graphics2.ico differ diff --git a/Resources/Icons/graphics3.ico b/Resources/Icons/graphics3.ico new file mode 100644 index 0000000..321c45e Binary files /dev/null and b/Resources/Icons/graphics3.ico differ diff --git a/Resources/Icons/text-x-preview.ico b/Resources/Icons/text-x-preview.ico new file mode 100644 index 0000000..6544edc Binary files /dev/null and b/Resources/Icons/text-x-preview.ico differ diff --git a/Resources/Images/file.png b/Resources/Images/file.png new file mode 100644 index 0000000..5d2ec98 Binary files /dev/null and b/Resources/Images/file.png differ diff --git a/Resources/Images/graphics16x16.png b/Resources/Images/graphics16x16.png new file mode 100644 index 0000000..f83cc52 Binary files /dev/null and b/Resources/Images/graphics16x16.png differ diff --git a/Resources/Images/graphics2.png b/Resources/Images/graphics2.png new file mode 100644 index 0000000..64a88bf Binary files /dev/null and b/Resources/Images/graphics2.png differ diff --git a/Resources/Images/graphics3.png b/Resources/Images/graphics3.png new file mode 100644 index 0000000..7849f1b Binary files /dev/null and b/Resources/Images/graphics3.png differ diff --git a/Resources/Images/graphics32x32.png b/Resources/Images/graphics32x32.png new file mode 100644 index 0000000..5651533 Binary files /dev/null and b/Resources/Images/graphics32x32.png differ diff --git a/Resources/Images/group.png b/Resources/Images/group.png new file mode 100644 index 0000000..2c93c82 Binary files /dev/null and b/Resources/Images/group.png differ diff --git a/Resources/Images/profile.png b/Resources/Images/profile.png new file mode 100644 index 0000000..d56270d Binary files /dev/null and b/Resources/Images/profile.png differ diff --git a/Resources/Images/symbol.png b/Resources/Images/symbol.png new file mode 100644 index 0000000..137fbae Binary files /dev/null and b/Resources/Images/symbol.png differ diff --git a/Resources/Scripts/google-code-prettify/lang-apollo.js b/Resources/Scripts/google-code-prettify/lang-apollo.js new file mode 100644 index 0000000..7098baf --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-apollo.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, +null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]); diff --git a/Resources/Scripts/google-code-prettify/lang-clj.js b/Resources/Scripts/google-code-prettify/lang-clj.js new file mode 100644 index 0000000..542a220 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-clj.js @@ -0,0 +1,18 @@ +/* + Copyright (C) 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a], +["typ",/^:[\dA-Za-z-]+/]]),["clj"]); diff --git a/Resources/Scripts/google-code-prettify/lang-css.js b/Resources/Scripts/google-code-prettify/lang-css.js new file mode 100644 index 0000000..041e1f5 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/Resources/Scripts/google-code-prettify/lang-go.js b/Resources/Scripts/google-code-prettify/lang-go.js new file mode 100644 index 0000000..fc18dc0 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-go.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]); diff --git a/Resources/Scripts/google-code-prettify/lang-hs.js b/Resources/Scripts/google-code-prettify/lang-hs.js new file mode 100644 index 0000000..9d77b08 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-hs.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n \r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, +null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); diff --git a/Resources/Scripts/google-code-prettify/lang-lisp.js b/Resources/Scripts/google-code-prettify/lang-lisp.js new file mode 100644 index 0000000..02a30e8 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-lisp.js @@ -0,0 +1,3 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], +["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]); diff --git a/Resources/Scripts/google-code-prettify/lang-lua.js b/Resources/Scripts/google-code-prettify/lang-lua.js new file mode 100644 index 0000000..e83a3c4 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-lua.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], +["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); diff --git a/Resources/Scripts/google-code-prettify/lang-ml.js b/Resources/Scripts/google-code-prettify/lang-ml.js new file mode 100644 index 0000000..6df02d7 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-ml.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], +["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]); diff --git a/Resources/Scripts/google-code-prettify/lang-n.js b/Resources/Scripts/google-code-prettify/lang-n.js new file mode 100644 index 0000000..6c2e85b --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-n.js @@ -0,0 +1,4 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/, +a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/, +a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]); diff --git a/Resources/Scripts/google-code-prettify/lang-proto.js b/Resources/Scripts/google-code-prettify/lang-proto.js new file mode 100644 index 0000000..f006ad8 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-proto.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); diff --git a/Resources/Scripts/google-code-prettify/lang-scala.js b/Resources/Scripts/google-code-prettify/lang-scala.js new file mode 100644 index 0000000..60d034d --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-scala.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], +["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]); diff --git a/Resources/Scripts/google-code-prettify/lang-sql.js b/Resources/Scripts/google-code-prettify/lang-sql.js new file mode 100644 index 0000000..da705b0 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-sql.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i, +null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]); diff --git a/Resources/Scripts/google-code-prettify/lang-tex.js b/Resources/Scripts/google-code-prettify/lang-tex.js new file mode 100644 index 0000000..ce96fbb --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-tex.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]); diff --git a/Resources/Scripts/google-code-prettify/lang-vb.js b/Resources/Scripts/google-code-prettify/lang-vb.js new file mode 100644 index 0000000..07506b0 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-vb.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r Â\xa0

"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“â€'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i, +null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]); diff --git a/Resources/Scripts/google-code-prettify/lang-vhdl.js b/Resources/Scripts/google-code-prettify/lang-vhdl.js new file mode 100644 index 0000000..128b5b6 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-vhdl.js @@ -0,0 +1,3 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, +null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i], +["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]); diff --git a/Resources/Scripts/google-code-prettify/lang-wiki.js b/Resources/Scripts/google-code-prettify/lang-wiki.js new file mode 100644 index 0000000..9b0b448 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-wiki.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t Â\xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]); +PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]); diff --git a/Resources/Scripts/google-code-prettify/lang-xq.js b/Resources/Scripts/google-code-prettify/lang-xq.js new file mode 100644 index 0000000..e323ae3 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-xq.js @@ -0,0 +1,3 @@ +PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/], +["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/], +["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]); diff --git a/Resources/Scripts/google-code-prettify/lang-yaml.js b/Resources/Scripts/google-code-prettify/lang-yaml.js new file mode 100644 index 0000000..c38729b --- /dev/null +++ b/Resources/Scripts/google-code-prettify/lang-yaml.js @@ -0,0 +1,2 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); diff --git a/Resources/Scripts/google-code-prettify/prettify.css b/Resources/Scripts/google-code-prettify/prettify.css new file mode 100644 index 0000000..d44b3a2 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/Resources/Scripts/google-code-prettify/prettify.js b/Resources/Scripts/google-code-prettify/prettify.js new file mode 100644 index 0000000..eef5ad7 --- /dev/null +++ b/Resources/Scripts/google-code-prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p + + Images/group.png + Images/file.png + Images/profile.png + Images/symbol.png + Icons/22x22/document-open-folder.png + Icons/22x22/edit-4.png + Icons/22x22/edit-add-4.png + Icons/22x22/edit-remove-3.png + Icons/22x22/zoom-3.png + Icons/22x22/code-class.png + Icons/22x22/document-new-4.png + Icons/22x22/document-open-6.png + Icons/22x22/view-process-all.png + Icons/22x22/edit-copy-4.png + Icons/22x22/xconsole-2.png + Icons/22x22/insert-link-2.png + Icons/48x48/applications-graphics-5.png + Images/graphics2.png + Icons/22x22/gtk-about.png + Icons/48x48/application-x-gnome-saved-search.png + Icons/48x48/applications-system.png + Icons/48x48/forward.png + Icons/22x22/gtk-execute.png + Icons/22x22/gtk-cancel.png + Icons/text-x-preview.ico + Icons/22x22/gtk-delete.png + Icons/22x22/gtk-new.png + Icons/22x22/gtk-ok.png + Icons/22x22/gtk-properties.png + Icons/22x22/gtk-redo-ltr.png + Icons/22x22/gtk-refresh.png + Images/graphics32x32.png + Images/graphics3.png + + diff --git a/Resources/webview.qrc b/Resources/webview.qrc new file mode 100644 index 0000000..60cb1a4 --- /dev/null +++ b/Resources/webview.qrc @@ -0,0 +1,6 @@ + + + Scripts/google-code-prettify/prettify.css + Scripts/google-code-prettify/prettify.js + + diff --git a/Screencast/Usage.gif b/Screencast/Usage.gif new file mode 100644 index 0000000..a7947da Binary files /dev/null and b/Screencast/Usage.gif differ diff --git a/Screenshot/blink_codesearch.png b/Screenshot/blink_codesearch.png new file mode 100644 index 0000000..8b8ffb9 Binary files /dev/null and b/Screenshot/blink_codesearch.png differ diff --git a/Screenshot/blink_filelisting.png b/Screenshot/blink_filelisting.png new file mode 100644 index 0000000..5eeadf8 Binary files /dev/null and b/Screenshot/blink_filelisting.png differ diff --git a/Screenshot/blink_multiple_lines.png b/Screenshot/blink_multiple_lines.png new file mode 100644 index 0000000..d2ccb78 Binary files /dev/null and b/Screenshot/blink_multiple_lines.png differ diff --git a/Screenshot/blink_multiple_symbols.png b/Screenshot/blink_multiple_symbols.png new file mode 100644 index 0000000..763f6f4 Binary files /dev/null and b/Screenshot/blink_multiple_symbols.png differ diff --git a/Screenshot/blink_regular_expression.png b/Screenshot/blink_regular_expression.png new file mode 100644 index 0000000..354cecb Binary files /dev/null and b/Screenshot/blink_regular_expression.png differ diff --git a/Screenshot/usage_drop_folder.png b/Screenshot/usage_drop_folder.png new file mode 100644 index 0000000..e1ac570 Binary files /dev/null and b/Screenshot/usage_drop_folder.png differ diff --git a/Screenshot/usage_new_profile.png b/Screenshot/usage_new_profile.png new file mode 100644 index 0000000..f73a39e Binary files /dev/null and b/Screenshot/usage_new_profile.png differ diff --git a/Storage/CDbmStorageHandler.cpp b/Storage/CDbmStorageHandler.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Storage/CDbmStorageHandler.h b/Storage/CDbmStorageHandler.h new file mode 100644 index 0000000..e69de29 diff --git a/Storage/CXmlStorageHandler.cpp b/Storage/CXmlStorageHandler.cpp new file mode 100644 index 0000000..84d81f9 --- /dev/null +++ b/Storage/CXmlStorageHandler.cpp @@ -0,0 +1,200 @@ +#include +#include +#include +#include + +#include +#include "CXmlStorageHandler.h" + +BYTE CXmlStorageHandler::loadFromFile(const QString& filename, QMap& profileMap, QMap& groupMap) +{ + QFile file(filename); + + if (!file.open(QIODevice::ReadOnly)) { + return LoadFileError; + } + + QDomDocument doc("ProfileML"); + + QString errMsg; + int errLine, errCol; + + if (!doc.setContent(&file, false, &errMsg, &errLine, &errCol)) { + qDebug() << "QDomDocument setContent() failed in CXmlStorageHandler::loadFromFile()!" << endl; + qDebug() << "err:" << errMsg << ", line:" << errLine << " column:" << errCol << endl; + file.close(); + return LoadFileError; + } + + file.close(); + + QDomElement docElement = doc.documentElement(); + + // start from doc first child + QDomNode docNode = docElement.firstChild(); + + while (!docNode.isNull()) { + QDomElement rootItem = docNode.toElement(); + + if (rootItem.tagName() == "profile") { + profileMap.clear(); + QDomNode node = rootItem.firstChild(); + + while (!node.isNull()) { + QDomElement element = node.toElement(); + if (!element.isNull()) { + if (element.tagName() == "profileItem") { + CProfileItem item; + + fillProfileItem(item, element); + profileMap[element.attribute("name", "")] = item; + } + node = node.nextSibling(); + } + } + } else if (rootItem.tagName() == "group") { + groupMap.clear(); + QDomNode node = rootItem.firstChild(); + + while (!node.isNull()) { + QDomElement element = node.toElement(); + if (!element.isNull()) { + if (element.tagName() == "groupItem") { + CGroupItem item; + + fillGroupItem(item, element); + groupMap[element.attribute("name", "")] = item; + } + node = node.nextSibling(); + } + } + } + docNode = docNode.nextSibling(); + } + + return NoError; +} + +QDomElement CXmlStorageHandler::createXMLNode(QDomDocument &document, const CProfileItem &profileItem) +{ + QDomElement element = document.createElement("profileItem"); + + element.setAttribute("name", profileItem.m_name); + element.setAttribute("srcDir", profileItem.m_srcDir); + element.setAttribute("srcMask", profileItem.m_srcMask); + element.setAttribute("headerMask", profileItem.m_headerMask); + element.setAttribute("tagUpdateDateTime", profileItem.m_tagUpdateDateTime); + element.setAttribute("profileCreateDateTime", profileItem.m_profileCreateDateTime); + element.setAttribute("labels", profileItem.m_labels); + + return element; +} + +QDomElement CXmlStorageHandler::createXMLNode(QDomDocument &document, const CGroupItem &groupItem) +{ + QDomElement element = document.createElement("groupItem"); + + element.setAttribute("name", groupItem.m_name); + element.setAttribute("profileList", groupItem.m_profileList); + element.setAttribute("tagUpdateDateTime", groupItem.m_tagUpdateDateTime); + element.setAttribute("groupCreateDateTime", groupItem.m_groupCreateDateTime); + element.setAttribute("labels", groupItem.m_labels); + + return element; +} + +void CXmlStorageHandler::fillProfileItem(CProfileItem& profileItemToBeFill, const QDomElement& element) +{ + QString name, srcDir, srcMask, headerMask; + QString tagUpdateDateTime, profileCreateDateTime; + + QString labels; + + name = element.attribute("name", ""); + srcDir = element.attribute("srcDir", ""); + srcMask = element.attribute("srcMask", ""); + headerMask = element.attribute("headerMask", ""); + labels = element.attribute("labels", ""); + + tagUpdateDateTime = element.attribute("tagUpdateDateTime", ""); + profileCreateDateTime = element.attribute("profileCreateDateTime", ""); + + CProfileItem profileItem(name, srcDir, srcMask, headerMask, + tagUpdateDateTime, profileCreateDateTime, labels); + + profileItemToBeFill = profileItem; +} + +void CXmlStorageHandler::fillGroupItem(CGroupItem& groupItemToBeFill, const QDomElement& element) +{ + QString name; + QString profileList; + QString tagUpdateDateTime, groupCreateDateTime; + QString labels; + + name = element.attribute("name", ""); + profileList = element.attribute("profileList", ""); + + tagUpdateDateTime = element.attribute("tagUpdateDateTime", ""); + groupCreateDateTime = element.attribute("groupCreateDateTime", ""); + + labels = element.attribute("labels", ""); + + CGroupItem groupItem(name, profileList, tagUpdateDateTime, groupCreateDateTime, labels); + + groupItemToBeFill = groupItem; +} + + +BYTE CXmlStorageHandler::saveToFile(const QString& filename, const QMap& profileMap, const QMap& groupMap) +{ + QDomDocument doc("ProfileML"); + + // record + QDomElement recordRoot = doc.createElement("record"); + doc.appendChild(recordRoot); + + // profile + QDomElement profileRoot = doc.createElement("profile"); + recordRoot.appendChild(profileRoot); + + CProfileItem profileItem; + foreach (profileItem, profileMap) { + QDomElement node = createXMLNode(doc, profileItem); + profileRoot.appendChild(node); + } + + // group + QDomElement groupRoot = doc.createElement("group"); + recordRoot.appendChild(groupRoot); + + CGroupItem groupItem; + foreach (groupItem, groupMap) { + QDomElement node = createXMLNode(doc, groupItem); + groupRoot.appendChild(node); + } + +#ifdef DEBUG_XML + QDomElement element = doc.createElement("profileItem"); + element.setAttribute("name", "a1"); + element.setAttribute("srcDir", "a2"); + element.setAttribute("srcMask", "a3"); + element.setAttribute("headerMask", "a4"); + element.setAttribute("labels", "a5"); + root.appendChild(element); +#endif + + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + //QMessageBox::warning(this, "Saving", "Failed to save file.", QMessageBox::Ok, QMessageBox::NoButton); /* <-- YCH modified 31/08/06, just for reference, to be removed */ + return SaveFileError; + } + + QTextStream ts(&file); + ts << doc.toString(); + file.close(); + + return NoError; +} + + diff --git a/Storage/CXmlStorageHandler.h b/Storage/CXmlStorageHandler.h new file mode 100644 index 0000000..ac9a914 --- /dev/null +++ b/Storage/CXmlStorageHandler.h @@ -0,0 +1,36 @@ +#ifndef CXML_STORAGE_HANDLER_H +#define CXML_STORAGE_HANDLER_H + +#include +#include "Utils/commonType.h" +#include "Model/CProfileItem.h" +#include "Model/CGroupItem.h" +#include "IStorageHandler.h" + +class CXmlStorageHandler : IStorageHandler +{ +public: + enum FileError { + NoError = 0, + LoadFileError = 1, + InvalidFileError = 2, + SaveFileError = 3 + }; + + CXmlStorageHandler() {}; + virtual ~CXmlStorageHandler() {}; + + BYTE loadFromFile(const QString& filename, QMap& profileMap, QMap& groupMap); + BYTE saveToFile(const QString& filename, const QMap& profileMap, const QMap& groupMap); + +private: + QDomElement createXMLNode(QDomDocument& document, const CProfileItem& profileItem); + QDomElement createXMLNode(QDomDocument& document, const CGroupItem& groupItem); + + void fillProfileItem(CProfileItem& profileItemToBeFill, const QDomElement& element); + void fillGroupItem(CGroupItem& groupItemToBeFill, const QDomElement& element); + +}; + +#endif // CXML_STORAGE_HANDLER_H + diff --git a/Storage/IStorageHandler.h b/Storage/IStorageHandler.h new file mode 100644 index 0000000..692a5d4 --- /dev/null +++ b/Storage/IStorageHandler.h @@ -0,0 +1,19 @@ +#ifndef ISTORAGE_HANDLER_H +#define ISTORAGE_HANDLER_H + +#include "Utils/commonType.h" + +// interface for storage handler + +class IStorageHandler { +public: + IStorageHandler() {}; + virtual ~IStorageHandler() {}; + + virtual BYTE loadFromFile(const QString& filename, QMap& profileList, QMap& groupList) = 0; + virtual BYTE saveToFile(const QString& filename, const QMap& profileList, const QMap& groupList) = 0; +}; + +#endif // ISTORAGE_HANDLER_H + + diff --git a/Utils/CUtils.cpp b/Utils/CUtils.cpp new file mode 100644 index 0000000..65f64bc --- /dev/null +++ b/Utils/CUtils.cpp @@ -0,0 +1,231 @@ +#include "CUtils.h" + +#include + +CUtils::CUtils() +{ + +} + +CUtils::~CUtils() +{ + +} + +// from John Suykerbuyk in lists.trolltech.com +bool CUtils::removeDirectory(QDir &aDir) +{ + bool has_err = false; + if (aDir.exists()) + { + QFileInfoList entries = aDir.entryInfoList(QDir::NoDotAndDotDot | + QDir::Dirs | QDir::Files); + int count = entries.size(); + for (int idx = 0; ((idx < count) && (!has_err)); idx++) + { + QFileInfo entryInfo = entries[idx]; + QString path = entryInfo.absoluteFilePath(); + if (entryInfo.isDir()) + { + QDir dirToRemove(path); + has_err = CUtils::removeDirectory(dirToRemove); + } + else + { + QFile file(path); + if (!file.remove()) + has_err = true; + } + } + if (!aDir.rmdir(aDir.absolutePath())) + has_err = true; + } + return(has_err); +} + +void CUtils::bufLog(unsigned char* buffer, long size) +{ + long i; + + printf("size = %ld\n", size); + for (i = 0; i < size; i++) { + printf("%02X ", buffer[i]); + if ((i != 0) && ((i+1) % 25 == 0)) { + printf("\n"); + } + } + printf("\n"); +} + +QString CUtils::bufToQString(unsigned char* buffer, long size) +{ + long i; + QString result = QString(""); + QString tmpStr; + + for (i = 0; i < size; i++) { + tmpStr= QString("%1 ").arg(buffer[i], 2, 16, QLatin1Char('0')); // hex string + result += tmpStr; + } + + return result; +} + + +void CUtils::putByte(BYTE* buffer, BYTE in) +{ + buffer[0] = in; +} + +void CUtils::putWord(BYTE* buffer, WORD in) +{ + buffer[0] = static_cast (in >> 8); + buffer[1] = static_cast (in); +} + +void CUtils::putDWord(BYTE* buffer, DWORD in) +{ + buffer[0] = static_cast (in >> 24); + buffer[1] = static_cast (in >> 16); + buffer[2] = static_cast (in >> 8); + buffer[3] = static_cast (in); +} + +BYTE CUtils::getByte(BYTE* buffer) +{ + BYTE out; + out = static_cast (buffer[0]); + return out; +} + +WORD CUtils::getWord(BYTE* buffer) +{ + WORD out; + out = (static_cast (buffer[0]) << 8) + (static_cast (buffer[1])); + return out; +} + +DWORD CUtils::getDWord(BYTE* buffer) +{ + DWORD out; + out = (static_cast (buffer[0]) << 24) + (static_cast (buffer[1]) << 16) + + (static_cast (buffer[2]) << 8) + (static_cast (buffer[3])); + return out; +} + +void CUtils::encode(BYTE *buffer, long& bufLen) +{ + long updatedBufLen; + static BYTE encodeDecodeBuf[ENCODE_DECODE_BUFFER_LEN]; + + encodeDWORDSeq((BYTE*) buffer, bufLen, encodeDecodeBuf, updatedBufLen); + + // copy back to buffer + memset(buffer, 0, bufLen); + memcpy(buffer, encodeDecodeBuf, updatedBufLen); + + // update buffer length + bufLen = updatedBufLen; +} + +void CUtils::decode(BYTE *buffer, long& bufLen) +{ + long updatedBufLen; + static BYTE encodeDecodeBuf[ENCODE_DECODE_BUFFER_LEN]; + + decodeDWORDSeq((BYTE*) buffer, bufLen, encodeDecodeBuf, updatedBufLen); + + // copy back to buffer + memset(buffer, 0, bufLen); + memcpy(buffer, encodeDecodeBuf, updatedBufLen); + + // update buffer length + bufLen = updatedBufLen; +} + +bool CUtils::encodeDWORDSeq(BYTE *inBuf, long inBufLen, BYTE* outBuf, long& outBufLen) +{ + DWORD dwordExtracted; + long inIdx = 0; + long outIdx = 0; + long dwordSize = sizeof(DWORD); + + BYTE encodedByte; + WORD encodedWord; + DWORD encodedDWord; + + if (inBufLen % dwordSize != 0) { + return false; + } + + outBufLen = 0; + + do { + dwordExtracted = getDWord(&(inBuf[inIdx])); + + if (dwordExtracted <= ENCODE_USE_1_BYTE) { + encodedByte = static_cast (dwordExtracted); + encodedByte |= MASK_HEADER_BYTE; + putByte(&(outBuf[outIdx]), encodedByte); + outIdx += 1; + outBufLen += 1; + } else if (dwordExtracted <= ENCODE_USE_2_BYTE) { + encodedWord = static_cast (dwordExtracted); + encodedWord |= MASK_HEADER_WORD; + putWord(&(outBuf[outIdx]), encodedWord); + outIdx += 2; + outBufLen += 2; + } else if (dwordExtracted <= ENCODE_USE_4_BYTE) { + encodedDWord = static_cast (dwordExtracted); + encodedDWord |= MASK_HEADER_DWORD; + putDWord(&(outBuf[outIdx]), encodedDWord); + outIdx += 4; + outBufLen += 4; + } + inIdx += dwordSize; + + } while (inIdx < inBufLen); + return true; +} + +bool CUtils::decodeDWORDSeq(BYTE *inBuf, long inBufLen, BYTE* outBuf, long& outBufLen) +{ + long inIdx = 0; + long outIdx = 0; + + BYTE byteExtracted; + + BYTE decodedByte; + WORD decodedWord; + DWORD decodedDWord; + + outBufLen = 0; + + do { + byteExtracted = getByte(&(inBuf[inIdx])); + + if ((byteExtracted & HEADER_BIT_1_MASK) == 0) { // 1 byte length + decodedByte = getByte(&(inBuf[inIdx])) & MASK_WITHOUT_HEADER_BYTE; + putDWord(&(outBuf[outIdx]), static_cast (decodedByte)); + inIdx += 1; + } else if ((byteExtracted & HEADER_BIT_2_MASK) == 0) { // 2 byte length + decodedWord = getWord(&(inBuf[inIdx])) & MASK_WITHOUT_HEADER_WORD; + putDWord(&(outBuf[outIdx]), static_cast (decodedWord)); + inIdx += 2; + } else { // 4 byte length + decodedDWord = getDWord(&(inBuf[inIdx])) & MASK_WITHOUT_HEADER_DWORD; + putDWord(&(outBuf[outIdx]), static_cast (decodedDWord)); + inIdx += 4; + } + outIdx += 4; + outBufLen += 4; + + } while (inIdx < inBufLen); + + return true; + + +} + + + diff --git a/Utils/CUtils.h b/Utils/CUtils.h new file mode 100644 index 0000000..fcd0c4c --- /dev/null +++ b/Utils/CUtils.h @@ -0,0 +1,63 @@ +#ifndef CUITLS_H +#define CUITLS_H + +#include +#include + +#include "commonType.h" + +class CUtils +{ +public: + CUtils(); + ~CUtils(); + + // recursively remove a directory + static bool removeDirectory(QDir &aDir); + + static void bufLog(unsigned char* buffer, long size); + static QString bufToQString(unsigned char* buffer, long size); + + // for convenient use + static void encode(BYTE *buffer, long& bufLen); + static void decode(BYTE *buffer, long& bufLen); + + // max allowed bit for each long here is 30, as using 2 bit for header + // note: big endian is expected, be careful of little endian + static bool encodeDWORDSeq(BYTE *inBuf, long inBufLen, BYTE* outBuf, long& outBufLen); + static bool decodeDWORDSeq(BYTE *inBuf, long inBufLen, BYTE* outBuf, long& outBufLen); + + static void putByte(BYTE* buffer, BYTE in); + static void putWord(BYTE* buffer, WORD in); + static void putDWord(BYTE* buffer, DWORD in); + + static BYTE getByte(BYTE* buffer); + static WORD getWord(BYTE* buffer); + static DWORD getDWord(BYTE* buffer); + +private: + + // for encode + static const DWORD ENCODE_USE_1_BYTE = 0x7F; // 01111111 + static const DWORD ENCODE_USE_2_BYTE = 0x3FFF; // 00111111 11111111 + static const DWORD ENCODE_USE_4_BYTE = 0x3FFFFFFF; // 00111111 11111111 11111111 11111111 + + static const BYTE MASK_HEADER_BYTE = 0x00; // 00 i.e. 00000000 + static const WORD MASK_HEADER_WORD = 0x8000; // 10 i.e. 10000000 00000000 + static const DWORD MASK_HEADER_DWORD = 0xC0000000; // 11 i.e. 11000000 00000000 00000000 00000000 + + // for decode + static const BYTE HEADER_BIT_1_MASK = 0x80; // 10000000 + static const BYTE HEADER_BIT_2_MASK = 0x40; // 01000000 + + static const BYTE MASK_WITHOUT_HEADER_BYTE = 0x7F; // 01111111 + static const WORD MASK_WITHOUT_HEADER_WORD = 0x3FFF; // 00111111 11111111 + static const DWORD MASK_WITHOUT_HEADER_DWORD = 0x3FFFFFFF; // 00111111 11111111 11111111 11111111 + + static const long ENCODE_DECODE_BUFFER_LEN = 5000; + + +}; + + +#endif diff --git a/Utils/commonType.h b/Utils/commonType.h new file mode 100644 index 0000000..5c1b688 --- /dev/null +++ b/Utils/commonType.h @@ -0,0 +1,11 @@ +#ifndef COMMON_TYPE_H +#define COMMON_TYPE_H + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +enum enum_TRACE_LEVEL {TRACE_DEBUG, TRACE_INFO, TRACE_WARNING, TRACE_ERROR}; +typedef enum enum_TRACE_LEVEL TRACE_LEVEL; + +#endif // COMMON_TYPE_H diff --git a/Utils/plugins/dbmplugin/dbmplugin.cpp b/Utils/plugins/dbmplugin/dbmplugin.cpp new file mode 100644 index 0000000..1d446a1 --- /dev/null +++ b/Utils/plugins/dbmplugin/dbmplugin.cpp @@ -0,0 +1,17 @@ +static int nextId = 0; // zero represents an invalid ID + + +DbmInterfacePlugin::~DbmInterfacePlugin() +{ + QMapIterator i(dbptrs); + while (i.hasNext()) { + i.next(); + close(i.key()); + } +} + + +Q_EXPORT_PLUGIN(DbmPlugin, DbmInterfacePlugin) + + + diff --git a/Utils/plugins/dbmplugin/dbmplugin.h b/Utils/plugins/dbmplugin/dbmplugin.h new file mode 100644 index 0000000..6369aad --- /dev/null +++ b/Utils/plugins/dbmplugin/dbmplugin.h @@ -0,0 +1,33 @@ +#ifndef DBMPLUGIN_H +#define DBMPLUGIN_H + +class Info +{ + public: + Info(void *_db=0, const QString &_dbmName=QString()) + : db(_db), dbmName(_dbmName) {} + + void *db; + QString dbmName; +}; + +class DbmInterfacePlugin : public QObject, + public DbmInterface +{ + Q_OBJECT + Q_INTERFACES(DbmInterface) + + public: + ~DbmInterfacePlugin(); + + int open(const QString &filename); + void close(int id); + QStringList lookup(int id, const QString &key); + + private: + QMap dbptrs; +}; + + +#endif + diff --git a/Utils/plugins/dbmplugin/dbmplugin.pro b/Utils/plugins/dbmplugin/dbmplugin.pro new file mode 100644 index 0000000..f19919f --- /dev/null +++ b/Utils/plugins/dbmplugin/dbmplugin.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +#LIBS += -ldb_cxx -ldb -lgdbm +LIBS += -ldb47 +INCLUDEPATH += ../external +#DESTDIR = ../plugins +HEADERS = dbmplugin.h +SOURCES = dbmplugin.cpp + diff --git a/Utils/qTag/interfaces.h b/Utils/qTag/interfaces.h new file mode 100644 index 0000000..6bb3751 --- /dev/null +++ b/Utils/qTag/interfaces.h @@ -0,0 +1,11 @@ +class DbmInterface +{ + public: + virtual ~DbmInterface() {} + virtual int open(const QString &filename) = 0; + virtual void close(int id) = 0; + virtual QStringList lookup(int id, const QString &key) = 0; +}; + +Q_DECLARE_INTERFACE(DbmInterface, "profileloader.DbmInterface/1.0") + diff --git a/Utils/qTag/keyword.txt b/Utils/qTag/keyword.txt new file mode 100644 index 0000000..923293f --- /dev/null +++ b/Utils/qTag/keyword.txt @@ -0,0 +1,31 @@ +goto break return continue asm +case default +if else switch +while for do +sizeof +int long short char void +signed unsigned float double +struct union enum typedef +static register auto volatile extern const + +new delete this friend using +public protected private +inline virtual explicit export bool wchar_t +throw try catch +operator typeid +and bitor or xor compl bitand and_eq or_eq xor_eq not not_eq +const_cast +static_cast +dynamic_cast +reinterpret_cast +mutable +class +typename +template +namespace +NPOS +true +false + + + diff --git a/Utils/qTag/pyclean.py b/Utils/qTag/pyclean.py new file mode 100644 index 0000000..61e39f8 --- /dev/null +++ b/Utils/qTag/pyclean.py @@ -0,0 +1,100 @@ +#!/usr/bin/python + +# History +# Version Date Creator Remarks +# 1.0 14 Feb 08 YCH Initial version + +import glob +import os + +import string +import getopt, sys + +removeMaskOptionList = ['makefile', 'debug', 'release'] + +removeMaskListDict = dict() + +removeMaskListDict['release'] = [ +"release/*.ii", +"release/*.o", +"release/moc*.cpp", +"release/*.exe", +"release/qrc*.cpp", +"ui_*.h" +] + +removeMaskListDict['debug'] = [ +"debug\*.ii", +"debug\*.o", +"debug\moc*.cpp", +"debug\*.exe", +"debug\qrc*.cpp", +"ui_*.h" +] + +removeMaskListDict['makefile'] = [ +"*.o", +"Makefile*.*", +"Makefile*", +"*.Debug", +"*.Release", +] + +def usage(): + print "pyclean" + print "Usage [--all] [--makefile] [--debug] [--release]" + print "" + +def main(): + + bClean = dict() + for removeMaskOption in removeMaskOptionList: + bClean[removeMaskOption] = False # False initially + + shortOptionStr = "" + longOptionList = removeMaskOptionList + ["all"] + + try: + optArgList, argList = getopt.getopt(sys.argv[1:], shortOptionStr, longOptionList) + except getopt.GetoptError, err: + print str(err) + usage() + sys.exit(2) + + if len(optArgList) == 0: + usage() + sys.exit(2) + + for opt, arg in optArgList: + bValidOpt = False + for removeMaskOption in removeMaskOptionList: + if opt == "--" + removeMaskOption: + bClean[removeMaskOption] = True + bValidOpt = True + if opt == "--" + "all": + for removeMaskOption in removeMaskOptionList: + bClean[removeMaskOption] = True + bValidOpt = True + + if bValidOpt == False: + assert False, "unhandled option" + + for removeMaskOption in removeMaskOptionList: + if bClean[removeMaskOption] == True: + print removeMaskOption + ":" + print + currentRemoveMaskList = removeMaskListDict[removeMaskOption] + + for removeMask in currentRemoveMaskList: + globList = glob.glob(removeMask) + for globItem in globList: + print "removing " + globItem + "..." + os.remove(globItem) + + +if __name__ == "__main__": + main() + + + + diff --git a/Utils/qTag/qTag.cpp b/Utils/qTag/qTag.cpp new file mode 100644 index 0000000..8642de9 --- /dev/null +++ b/Utils/qTag/qTag.cpp @@ -0,0 +1,168 @@ +/* vim: set fdm=marker : */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include // for getopt + +#include + +#include "qTagApp.h" +#include "qTagger.h" + +#include "CUtils.h" + +#include "CTagResultItem.h" + +using namespace std; + +int main(int argc, char *argv[]) +{ + QTagApplication app(argc, argv); + QTagger tagger; + QString tagToQuery; + + QString inputFileName(QTagger::kQTAG_DEFAULT_INPUTLIST_FILE); // default input file name + QString tagDbFileName(QTagger::kQTAG_DEFAULT_TAGDBNAME); // default tag database file name + QString configFileName(QTagger::kQTAG_CONFIG_FILE); + + Qt::CaseSensitivity caseSensitive; + + bool cFlag = false; // create tag + bool qFlag = false; // query tag + bool tFlag = false; + bool iFlag = false; // default to false, i.e. case sensitive in query + bool dFlag = false; // debug flag + bool lFlag = false; // input file + + char *qValue = NULL; + char *tValue = NULL; + char *lValue = NULL; + + int cOpt; + + while ((cOpt = getopt(argc, argv, "cq:t:i:d:l")) != -1) { + switch (cOpt) + { + case 'c': + cFlag = true; + break; + case 'q': + qFlag = true; + qValue = optarg; + break; + case 't': + tFlag = true; + tValue = optarg; + break; + case 'i': + iFlag = true; + break; + case 'd': + dFlag = true; + break; + case 'l': + lFlag = true; + lValue = optarg; + break; + + case '?': + if ((optopt == 'q') || (optopt == 't') || (optopt == 'l')) { + fprintf (stderr, "Option -%c requires an argument.\n", optopt); + } else if (isprint(optopt)) { + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + } else { + fprintf (stderr, + "Unknown option character `\\x%x'.\n", + optopt); + } + } + } + + // Case Sensitivity + if (iFlag) { + caseSensitive = Qt::CaseInsensitive; + } else { + caseSensitive = Qt::CaseSensitive; + } + + // handling of input file + if (lFlag) { + inputFileName = lValue; + } + + // handling of tag database file + if (tFlag) { + tagDbFileName = tValue; + } + + if (cFlag) { // remove existing env and db files first + QElapsedTimer timer; + timer.start(); + + T_OutputItemList fileList; + + CSourceFileList::loadFileList(inputFileName, fileList); + + qDebug() << "Processing File..." << endl; + + tagger.createTag(fileList); + tagger.writeTagDb(tagDbFileName); + + qDebug() << "Operation took" << QString::number(((double) timer.elapsed() / 1000), 'f', 3) << "s" << endl; + } + + // handling of tag to be query + if (qFlag) { + // read currently load profile + QFile qTagConfigFile(QCoreApplication::applicationDirPath() + "/" + configFileName); + + if (!qTagConfigFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Cannot open config file (" << configFileName << ") for reading!" << endl; + return -1; + } + + QTextStream qTagConfigFileIn(&qTagConfigFile); + + QString configStr; + QString profileLoadStr = "profileLoad="; + + while (!qTagConfigFileIn.atEnd()) { + configStr = qTagConfigFileIn.readLine(); + if (configStr.startsWith(profileLoadStr)) { + configStr.remove(0, profileLoadStr.length()); + + tagDbFileName = QString(QCoreApplication::applicationDirPath() + "/" + QTagger::kQTAG_TAGS_DIR) + "/" + configStr + "/" + tagDbFileName; + inputFileName = QString(QCoreApplication::applicationDirPath() + "/" + QTagger::kQTAG_TAGS_DIR) + "/" + configStr + "/" + inputFileName; + break; + } + } + + qTagConfigFile.close(); + + // start query + tagToQuery = QString(qValue); + + QList resultList; + QString tagToQueryFiltered; + + tagger.queryTag(inputFileName, tagDbFileName, tagToQuery, tagToQueryFiltered, resultList, caseSensitive); + + foreach (const CTagResultItem& result, resultList) { + //cout << "[" << result.functionSignature_.toStdString() << "]" << endl; + cout << result << endl; + } + } + + return 0; +} + + diff --git a/Utils/qTag/qTag.pro b/Utils/qTag/qTag.pro new file mode 100644 index 0000000..bcbf302 --- /dev/null +++ b/Utils/qTag/qTag.pro @@ -0,0 +1,29 @@ +#QMAKE_CC = gcc +QMAKE_CXX = g++ + +TEMPLATE = app + +#QT = core +QT -= gui + +CONFIG += console warn_on +LIBS += -L"../external" +INCLUDEPATH += "../" +INCLUDEPATH += "../../Model/qTagger/" + +SOURCES += qTag.cpp \ + qTagApp.cpp \ + ../../Model/qTagger/CTagResultItem.cpp \ + ../../Model/qTagger/qTagger.cpp \ + ../../Model/COutputItem.cpp \ + ../../Model/qTagger/CSourceFileList.cpp \ + ../CUtils.cpp \ + +HEADERS += qTagApp.h \ + ../../Model/qTagger/CTagResultItem.h \ + ../../Model/qTagger/qTagger.h \ + ../../Model/COutputItem.h \ + ../../Model/qTagger/CSourceFileList.h \ + ../CUtils.h \ + + diff --git a/Utils/qTag/qTagApp.cpp b/Utils/qTag/qTagApp.cpp new file mode 100644 index 0000000..950e1e3 --- /dev/null +++ b/Utils/qTag/qTagApp.cpp @@ -0,0 +1,15 @@ +#include "qTagApp.h" + + +QTagApplication::QTagApplication(int& argc, char**& argv) +: QCoreApplication(argc, argv) +{ + + +} + +QTagApplication::~QTagApplication() +{ + +} + diff --git a/Utils/qTag/qTagApp.h b/Utils/qTag/qTagApp.h new file mode 100644 index 0000000..1bd50df --- /dev/null +++ b/Utils/qTag/qTagApp.h @@ -0,0 +1,18 @@ +#ifndef QTAGAPP_H +#define QTAGAPP_H + +#include + +class QTagApplication : public QCoreApplication +{ + Q_OBJECT +public: + QTagApplication(int& argc, char**& argv); + + virtual ~QTagApplication(); + + +}; + + +#endif diff --git a/Utils/qTag/test/TestCRecordPool.cpp b/Utils/qTag/test/TestCRecordPool.cpp new file mode 100644 index 0000000..e7498ec --- /dev/null +++ b/Utils/qTag/test/TestCRecordPool.cpp @@ -0,0 +1,31 @@ +#include "TestCRecordPool.h" + +void TestCRecordPool::initTestCase() +{ + m_record = new CRecord("test", 1); + m_recordItem = new CRecordItem(1); + m_record->addItem(m_recordItem); +} + +void TestCRecordPool::compress() +{ + unsigned char buffer[5000]; + unsigned char testData1[] = {0, 1}; + long bufLen; + long maxBufferLen = 5000; + + QVERIFY(m_record != 0); + m_record->packBuffer(static_cast (buffer), bufLen, 5000); + QCOMPARE(buffer, testData1); + +} + +void TestCRecordPool::cleanupTestCase() +{ + delete m_record; + m_record = 0; +} + +QTEST_MAIN(TestCRecordPool) + + diff --git a/Utils/qTag/test/TestCRecordPool.h b/Utils/qTag/test/TestCRecordPool.h new file mode 100644 index 0000000..94ed323 --- /dev/null +++ b/Utils/qTag/test/TestCRecordPool.h @@ -0,0 +1,25 @@ +#ifndef TESTCRECORDPOOL_H + +#define TESTCRECORDPOOL_H +#include +#include "CRecordPool.h" + +class TestCRecordPool: public QObject +{ +Q_OBJECT +public: + TestCRecordPool() {}; + ~TestCRecordPool() {}; +private slots: + void initTestCase(); + void compress(); + void cleanupTestCase(); + +private: + CRecord* m_record; + CRecordItem* m_recordItem; + +}; + +#endif // TESTCRECORDPOOL_H + diff --git a/Utils/qTag/test/TestCRecordPool.pro b/Utils/qTag/test/TestCRecordPool.pro new file mode 100644 index 0000000..2e5168f --- /dev/null +++ b/Utils/qTag/test/TestCRecordPool.pro @@ -0,0 +1,19 @@ +#QMAKE_CC = gcc +QMAKE_CXX = g++ + +#TEMPLATE = app + +QT -= gui + +CONFIG += console warn_on qtestlib +INCLUDEPATH += "../" "../../" + +SOURCES += TestCRecordPool.cpp \ + ../CRecordPool.cpp \ + ../../CUtils.cpp \ + +HEADERS += TestCRecordPool.h \ + ../CRecordPool.h \ + ../../CUtils.h \ + + diff --git a/Utils/test/TestCUtils.cpp b/Utils/test/TestCUtils.cpp new file mode 100644 index 0000000..eae63c5 --- /dev/null +++ b/Utils/test/TestCUtils.cpp @@ -0,0 +1,172 @@ +#include "TestCUtils.h" + +void TestCUtils::initTestCase() +{ + qRegisterMetaType ("BYTE_VECTOR"); + +} + +void TestCUtils::encode_data() +{ + QTest::addColumn("inBuf"); + QTest::addColumn("expectedBuf"); + + BYTE_VECTOR bufInput, bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x00 << 0x01; + bufExpected << 0x01; + QTest::newRow("encodeToByte") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x00 << 0x7F; + bufExpected << 0x7F; + QTest::newRow("encodeToByteBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x00 << 0x80; + bufExpected << 0x80 << 0x80; + QTest::newRow("encodeToWord") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x3F << 0xFF; + bufExpected << 0xBF << 0xFF; + QTest::newRow("encodeToWordBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x40 << 0x00; + bufExpected << 0xC0 << 0x00 << 0x40 << 0x00; + QTest::newRow("encodeToDWord") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x3F << 0xFF << 0xFF << 0xFF; + bufExpected << 0xFF << 0xFF << 0xFF << 0xFF; + QTest::newRow("encodeToDWordBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x00 << 0x00 << 0x00 << 0x7F << 0x00 << 0x00 << 0x00 << 0x80; + bufExpected << 0x7F << 0x80 << 0x80; + QTest::newRow("encodeToByteWord") << bufInput << bufExpected; + + // due to stored as little endian, commented by default + //bufInput.clear(); bufExpected.clear(); + //bufInput << 0x40 << 0x00 << 0x00 << 0x00 << 0x6D << 0x00 << 0x00 << 0x00; + //bufExpected << 0xFF; + //QTest::newRow("encodeErrRunTimeReturnSizeZero") << bufInput << bufExpected; + +} + +void TestCUtils::encode() +{ + QFETCH(BYTE_VECTOR, inBuf); + QFETCH(BYTE_VECTOR, expectedBuf); + + BYTE inBufByte[BUFLEN]; + BYTE outBufByte[BUFLEN]; + BYTE expectedBufByte[BUFLEN]; + + long outBufLen; + int i; + + // input, output + for (i = 0; i < inBuf.size(); ++i) { + inBufByte[i] = inBuf[i]; + } + CUtils::encodeDWORDSeq(inBufByte, inBuf.size(), outBufByte, outBufLen); + + // expected, expected length + QCOMPARE(outBufLen, static_cast (expectedBuf.size())); + + for (i = 0; i < expectedBuf.size(); ++i) { + expectedBufByte[i] = expectedBuf[i]; + } + + // comparision + QString outStr = CUtils::bufToQString(outBufByte, outBufLen);; + QString expectedStr = CUtils::bufToQString(expectedBufByte, outBufLen); + + QCOMPARE(outStr, expectedStr); +} + +void TestCUtils::decode_data() +{ + QTest::addColumn("inBuf"); + QTest::addColumn("expectedBuf"); + + BYTE_VECTOR bufInput, bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x01; + bufExpected << 0x00 << 0x00 << 0x00 << 0x01; + QTest::newRow("decodeFromByte") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x7F; + bufExpected << 0x00 << 0x00 << 0x00 << 0x7F; + QTest::newRow("decodeFromByteBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x80 << 0x80; + bufExpected << 0x00 << 0x00 << 0x00 << 0x80; + QTest::newRow("decodeFromWord") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0xBF << 0xFF; + bufExpected << 0x00 << 0x00 << 0x3F << 0xFF; + QTest::newRow("decodeFromWordBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0xC0 << 0x00 << 0x40 << 0x00; + bufExpected << 0x00 << 0x00 << 0x40 << 0x00; + QTest::newRow("decodeFromDWord") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0xFF << 0xFF << 0xFF << 0xFF; + bufExpected << 0x3F << 0xFF << 0xFF << 0xFF; + QTest::newRow("decodeFromDWordBoundary") << bufInput << bufExpected; + + bufInput.clear(); bufExpected.clear(); + bufInput << 0x7F << 0x80 << 0x80; + bufExpected << 0x00 << 0x00 << 0x00 << 0x7F << 0x00 << 0x00 << 0x00 << 0x80; + QTest::newRow("decodeFromByteWord") << bufInput << bufExpected; +} + +void TestCUtils::decode() +{ + QFETCH(BYTE_VECTOR, inBuf); + QFETCH(BYTE_VECTOR, expectedBuf); + + BYTE inBufByte[BUFLEN]; + BYTE outBufByte[BUFLEN]; + BYTE expectedBufByte[BUFLEN]; + + long outBufLen; + int i; + + // input, output + for (i = 0; i < inBuf.size(); ++i) { + inBufByte[i] = inBuf[i]; + } + CUtils::decodeDWORDSeq(inBufByte, inBuf.size(), outBufByte, outBufLen); + + // expected, expected length + QCOMPARE(outBufLen, static_cast (expectedBuf.size())); + + for (i = 0; i < expectedBuf.size(); ++i) { + expectedBufByte[i] = expectedBuf[i]; + } + + // comparision + QString outStr = CUtils::bufToQString(outBufByte, outBufLen);; + QString expectedStr = CUtils::bufToQString(expectedBufByte, outBufLen); + + QCOMPARE(outStr, expectedStr); +} + +void TestCUtils::cleanupTestCase() +{ +} + +QTEST_MAIN(TestCUtils) + + diff --git a/Utils/test/TestCUtils.h b/Utils/test/TestCUtils.h new file mode 100644 index 0000000..2a750bc --- /dev/null +++ b/Utils/test/TestCUtils.h @@ -0,0 +1,32 @@ +#ifndef TESTCUTILS_H + +#define TESTCUTILS_H +#include +#include "CUtils.h" + +typedef QVector BYTE_VECTOR; + +class TestCUtils: public QObject +{ +Q_OBJECT +public: + TestCUtils() {}; + ~TestCUtils() {}; +private slots: + void initTestCase(); + void encode_data(); + void encode(); + + void decode_data(); + void decode(); + void cleanupTestCase(); + +private: + static const long BUFLEN = 5000; + +}; + +Q_DECLARE_METATYPE(BYTE_VECTOR) + +#endif // TESTCUTILS_H + diff --git a/Utils/test/TestCUtils.pro b/Utils/test/TestCUtils.pro new file mode 100644 index 0000000..1a60e3e --- /dev/null +++ b/Utils/test/TestCUtils.pro @@ -0,0 +1,16 @@ +#QMAKE_CC = gcc +QMAKE_CXX = g++ + +TEMPLATE = app + +QT -= gui + +CONFIG += console warn_on qtestlib +INCLUDEPATH += "../" + +SOURCES += TestCUtils.cpp \ + ../CUtils.cpp \ + +HEADERS += TestCUtils.h \ + ../CUtils.h \ + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..11d42d0 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,7 @@ +install: + - set QTDIR=C:\Qt\5.13.2\mingw73_32 + - set PATH=%PATH%;%QTDIR%\bin;C:\MinGW\bin +build_script: + - qmake blink.pro + - mingw32-make + diff --git a/blink b/blink new file mode 100755 index 0000000..79eb377 Binary files /dev/null and b/blink differ diff --git a/blink.pro b/blink.pro new file mode 100644 index 0000000..f0276ce --- /dev/null +++ b/blink.pro @@ -0,0 +1,82 @@ +#QMAKE_CC = gocache gcc +#QMAKE_CXX = gocache g++ + +TEMPLATE = app +#CONFIG += release + +QT += widgets xml network +RC_FILE = Resources/Icons/appIcons.rc +RESOURCES = Resources/app.qrc +#RESOURCES += Resources/webview.qrc + +INCLUDEPATH += "Utils" + +FORMS = Resources/Forms/mainWindow.ui \ + Resources/Forms/profileDialog.ui \ + Resources/Forms/groupDialog.ui \ + Resources/Forms/aboutDialog.ui \ + Resources/Forms/configDialog.ui + +SOURCES += main.cpp \ + Utils/CUtils.cpp \ + Display/CMainWindow.cpp \ + Display/CProfileDlg.cpp \ + Display/CGroupDlg.cpp \ + Display/CAboutDlg.cpp \ + Display/CProfileListWidget.cpp \ + Display/CGroupListWidget.cpp \ + Display/COutputListWidget.cpp \ + Display/CConfigDlg.cpp \ + Display/CEventFilterObj.cpp \ + Display/CSearchTextBrowser.cpp \ + Model/qTagger/CTagResultItem.cpp \ + Model/qTagger/qTagger.cpp \ + Model/qTagger/CSourceFileList.cpp \ + Model/CProfileListModel.cpp \ + Model/CGroupListModel.cpp \ + Model/COutputListModel.cpp \ + Model/CProfileManager.cpp \ + Model/CProfileUpdateThread.cpp \ + Model/CProfileLoadThread.cpp \ + Model/CGroupLoadThread.cpp \ + Model/CConfigManager.cpp \ + Model/CGroupItem.cpp \ + Model/CProfileItem.cpp \ + Model/COutputItem.cpp \ + Model/CRunCommand.cpp \ + Storage/CXmlStorageHandler.cpp \ + + +HEADERS += Utils/commonType.h \ + Utils/CUtils.h \ + Display/CMainWindow.h \ + Display/CProfileDlg.h \ + Display/CGroupDlg.h \ + Display/CAboutDlg.h \ + Display/CProfileListWidget.h \ + Display/CGroupListWidget.h \ + Display/COutputListWidget.h \ + Display/CConfigDlg.h \ + Display/CEventFilterObj.h \ + Display/CSearchTextBrowser.h \ + Model/qTagger/CTagResultItem.h \ + Model/qTagger/qTagger.h \ + Model/qTagger/CSourceFileList.h \ + Model/CProfileListModel.h \ + Model/CGroupListModel.h \ + Model/COutputListModel.h \ + Model/CProfileManager.h \ + Model/CProfileUpdateThread.h \ + Model/CProfileLoadThread.h \ + Model/CGroupLoadThread.h \ + Model/CConfigManager.h \ + Model/CProfileItem.h \ + Model/CGroupItem.h \ + Model/COutputItem.h \ + Model/CRunCommand.h \ + Storage/CXmlStorageHandler.h \ + Storage/IStorageHandler.h \ + + + + diff --git a/blinkAppImage/usr/share/applications/blink.desktop b/blinkAppImage/usr/share/applications/blink.desktop new file mode 100644 index 0000000..7c7e696 --- /dev/null +++ b/blinkAppImage/usr/share/applications/blink.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Application +Name=Blink +Exec=/usr/bin/blink +Icon=/usr/share/icons/hicolor/256x256/blink.png + diff --git a/blinkAppImage/usr/share/icons/hicolor/256x256/blink.png b/blinkAppImage/usr/share/icons/hicolor/256x256/blink.png new file mode 100644 index 0000000..7849f1b Binary files /dev/null and b/blinkAppImage/usr/share/icons/hicolor/256x256/blink.png differ diff --git a/build/Html/style.css b/build/Html/style.css new file mode 100644 index 0000000..4595ff8 --- /dev/null +++ b/build/Html/style.css @@ -0,0 +1,17 @@ +A:link {color: #0066FF; font-weight:bold; font-family: Consolas; text-decoration: none} +A:visited {color: #0066FF; font-weight:bold; font-family: Consolas; text-decoration: none} +A:active {color: #0066FF; font-weight:bold; font-family: Consolas; text-decoration: none} +A:hover {color: #0066FF; font-weight:bold; font-family: Consolas; text-decoration: underline} + +functionsig {color: #33F000; font-weight:bold; font-family: Consolas;} +code { background: #FAFAFA; display: table-row; font-family: Consolas; white-space: nowrap} +linenum {color: #9999CC; font-family: Consolas} + +keyword {color: #00CCCC; font-weight:bold} +body {background: #FAFAFA} + +.itemblock {margin: 1em 0em 1em 0.3em; padding: 0em} +.header {margin: 0; padding: 0em 0em 0.3em 0em} + + + diff --git a/build/blink b/build/blink new file mode 100755 index 0000000..4541949 Binary files /dev/null and b/build/blink differ diff --git a/build/blink.ini b/build/blink.ini new file mode 100644 index 0000000..110fcb9 --- /dev/null +++ b/build/blink.ini @@ -0,0 +1,21 @@ +[Setting] +DefaultEditor=/usr/bin/gvim +FileFilterCaseSensitive=false +ProfileFont="Sans Serif,22,-1,5,50,0,0,0,0,0" +SrcSubstDrv= +SymbolSearchCaseSensitive=false +TagDir=tags +TagSubstDrv= +TimeoutRunExtProgram= +TmpDir= +Transparency=false +ViewFilePanel=true +ViewProfilePanel=true +ViewToolbar=true +actionProfileAndGroupCaseSensitive=false + +[Window] +fileTabIndex=0 +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\xc2\0\0\0X\0\0\x6\b\0\0\x3\x1\0\0\0\xc2\0\0\0\x84\0\0\x6\b\0\0\x3\x1\0\0\0\0\0\0\0\0\x6@\0\0\0\xc2\0\0\0\x84\0\0\x6\b\0\0\x3\x1) +profileTabIndex=0 +splitter="351 990 " diff --git a/build/keyword.txt b/build/keyword.txt new file mode 100644 index 0000000..cb687fb --- /dev/null +++ b/build/keyword.txt @@ -0,0 +1,74 @@ +NPOS +and +and_eq +asm +auto +bitand +bitor +bool +break +case +char +class +compl +const +const_cast +continue +default +defined +do +double +dynamic_cast +else +enum +explicit +export +extern +false +float +for +friend +goto +if +include +inline +int +long +mutable +namespace +not +not_eq +operator +or +or_eq +public +protected +private +register +reinterpret_cast +return +short +signed +sizeof +static +static_cast +struct +switch +template +this +true +try +typedef +typeid +typename +union +unsigned +using +virtual +void +volatile +wchar_t +while +xor +xor_eq + diff --git a/build/qtag.conf b/build/qtag.conf new file mode 100644 index 0000000..af56b7b --- /dev/null +++ b/build/qtag.conf @@ -0,0 +1 @@ +profileLoad=blink diff --git a/build/record.xml b/build/record.xml new file mode 100644 index 0000000..e281343 --- /dev/null +++ b/build/record.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/clean_debug.py b/clean_debug.py new file mode 100644 index 0000000..1aaa4be --- /dev/null +++ b/clean_debug.py @@ -0,0 +1,18 @@ +import glob +import os + +removeMaskList = [ +"debug\*.ii", +"debug\*.o", +"debug\moc*.cpp", +"debug\*.exe", +"debug\qrc*.cpp", +"ui_*.h" +] + +for removeMask in removeMaskList: + globList = glob.glob(removeMask) + for globItem in globList: + os.remove(globItem) + + diff --git a/clean_makefile.py b/clean_makefile.py new file mode 100644 index 0000000..728544d --- /dev/null +++ b/clean_makefile.py @@ -0,0 +1,17 @@ +import glob +import os + +removeMaskList = [ +"*.o", +"Makefile*.*", +"Makefile*", +"*.Debug", +"*.Release", +] + +for removeMask in removeMaskList: + globList = glob.glob(removeMask) + for globItem in globList: + os.remove(globItem) + + diff --git a/clean_release.py b/clean_release.py new file mode 100644 index 0000000..fd8538b --- /dev/null +++ b/clean_release.py @@ -0,0 +1,18 @@ +import glob +import os + +removeMaskList = [ +"release/*.ii", +"release/*.o", +"release/moc*.cpp", +"release/*.exe", +"release/qrc*.cpp", +"ui_*.h" +] + +for removeMask in removeMaskList: + globList = glob.glob(removeMask) + for globItem in globList: + os.remove(globItem) + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6775fa5 --- /dev/null +++ b/main.cpp @@ -0,0 +1,71 @@ +#include "Display/CMainWindow.h" + +#include +#include + +#include + +#include "Display/CEventFilterObj.h" +#include "Model/CConfigManager.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + CMainWindow *window = new CMainWindow; + + CConfigManager* confManager; + confManager = CConfigManager::getInstance(); + + CXmlStorageHandler xmlStorageHandler; + + CProfileManager::getInstance()->setProfileFile("record.xml"); + CProfileManager::getInstance()->setStorageHandler(xmlStorageHandler); + CProfileManager::getInstance()->attachStorage(); + + // load profile list after storage ready + window->loadProfileList(); + + // load group list after storage ready + window->loadGroupList(); + + // Center the main window on screen for the first time + QDesktopWidget desktopWidget; // get desktop info + + QByteArray savedGeometry; + + savedGeometry = confManager->getValue("Window", "geometry").toByteArray(); + window->restoreGeometry(savedGeometry); + + QString splitterSizeStr; + QStringList splitterSizeStrList; + QList splitterSizeList; + + // tab widget + window->restoreTabWidgetPos(); + + // splitter + splitterSizeStr = confManager->getValue("Window", "splitter").toString(); + splitterSizeStr = splitterSizeStr.trimmed(); + + splitterSizeStrList = splitterSizeStr.split(" ", QString::SkipEmptyParts); + + foreach (const QString& splitterSize, splitterSizeStrList) { + splitterSizeList.append(splitterSize.toInt()); + } + + window->setSplitterSizes(splitterSizeList); + + qDebug() << desktopWidget.screenGeometry(); + + qDebug() << window->geometry(); + qDebug() << window->frameGeometry(); + + window->show(); + + // event filter for show/hide menuBar + CEventFilterObj *keyPressObj = new CEventFilterObj(); + app.installEventFilter(keyPressObj); + + return app.exec(); +} + diff --git a/profile_loader.ini b/profile_loader.ini new file mode 100644 index 0000000..c9f1b68 --- /dev/null +++ b/profile_loader.ini @@ -0,0 +1,10 @@ +[Setting] +ViewFilePanel=true +ViewProfilePanel=true +ViewToolbar=true + +[Window] +fileTabIndex=0 +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\xc9\0\0\0~\0\0\x5%\0\0\x2\xf7\0\0\0\xc9\0\0\0\xaa\0\0\x5%\0\0\x2\xf7\0\0\0\0\0\0\0\0\x6@\0\0\0\xc9\0\0\0\xaa\0\0\x5%\0\0\x2\xf7) +profileTabIndex=0 +splitter="381 726 " diff --git a/qtag.conf b/qtag.conf new file mode 100644 index 0000000..cd34548 --- /dev/null +++ b/qtag.conf @@ -0,0 +1 @@ +profileLoad=blink_repos