kscope-1.9.4/0000755000175000001440000000000011156714402012171 5ustar elahavuserskscope-1.9.4/app/0000755000175000001440000000000011156714402012751 5ustar elahavuserskscope-1.9.4/app/actions.h0000644000175000001440000000330111156714354014565 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __KSCOPE_ACTIONS_H__ #define __KSCOPE_ACTIONS_H__ #include #include namespace KScope { namespace App { class MainWindow; /** * Handles all main window actions. * The sole purpose of this class is to reduce the amount of code in * MainWindow. There is no functional reason for having it. * @author Elad Lahav */ class Actions : public QObject { Q_OBJECT public: Actions(MainWindow*); ~Actions(); void setup(); private: /** * A dynamically-generated list of open windows. */ QMenu* wndMenu_; inline MainWindow* mainWnd(); private slots: void query(QAction*); void showWindowMenu(); void setEditorViewMode(QAction*); }; } // namespace App } // namespace KScope #endif // __KSCOPE_ACTIONS_H__ kscope-1.9.4/app/stackwidget.cpp0000644000175000001440000001132511156714354015776 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include "stackwidget.h" namespace KScope { namespace App { /** * Class constructor. * @param widget The widget to display * @param parent Parent widget */ StackPage::StackPage(QWidget* widget, QWidget* parent) : QWidget(parent), Ui::StackPage(), widget_(widget) { // Create the UI. setupUi(this); label_->setText(widget->windowTitle()); layout()->addWidget(widget); // Handle title bar button clicks. connect(showButton_, SIGNAL(clicked()), this, SLOT(showWidget())); connect(closeButton_, SIGNAL(clicked()), this, SLOT(remove())); } /** * Class destructor. */ StackPage::~StackPage() { } /** * Displays the widget. */ void StackPage::showWidget() { widget_->show(); emit activated(this); } /** * Hides the widget, leaving only the title bar visible. */ void StackPage::hideWidget() { widget_->hide(); } /** * Destroys the page. */ void StackPage::remove() { emit removed(this); deleteLater(); } /** * Class constructor. * @param parent Parent widget */ StackWidget::StackWidget(QWidget* parent) : QWidget(parent), activePage_(NULL) { layout_ = new QVBoxLayout; layout_->setSpacing(0); layout_->setContentsMargins(0, 0, 0, 0); setLayout(layout_); } /** * Class destructor. */ StackWidget::~StackWidget() { } /** * Creates a new stack page that holds the given widget. * @param widget The widget to add */ void StackWidget::addWidget(QWidget* widget) { // Create a new page. StackPage* page = new StackPage(widget, this); pageList_.append(page); connect(page, SIGNAL(activated(StackPage*)), this, SLOT(setActivePage(StackPage*))); connect(page, SIGNAL(removed(StackPage*)), this, SLOT(removePage(StackPage*))); // Show the page and make it the active one. layout_->addWidget(page); page->show(); setActivePage(page); } /** * Creates a list of all widgets managed by the stack. * @return A list containing all widgets in the stack */ QList StackWidget::widgets() const { QList widgetList; QLinkedList::ConstIterator itr; for (itr = pageList_.begin(); itr != pageList_.end(); ++itr) widgetList.append((*itr)->widget()); return widgetList; } /** * Deletes all pages from the stack. */ void StackWidget::removeAll() { while (!pageList_.isEmpty()) delete pageList_.takeFirst(); activePage_ = NULL; } /** * Changes the active page in the stack. * This slot is called when a page shows its widget and emits the activated() * signal. The method needs to hide the widget on the previously active page. * @param page The newly activated page */ void StackWidget::setActivePage(StackPage* page) { // Nothing to do if this is already the active page. if (activePage_ == page) return; // Hide the widget of the previously active page. if (activePage_) activePage_->hideWidget(); // Set a new active page. activePage_ = page; } /** * Removes a page from the stack. * This slot is called when a page is closed and emits the removed() signal. If * it is the currently active page, a new active page is selected. * @param page The page to remove */ void StackWidget::removePage(StackPage* page) { // Remove from the list of pages. QLinkedList::Iterator itr; for (itr = pageList_.begin(); itr != pageList_.end(); ++itr) { if (*itr == page) { itr = pageList_.erase(itr); break; } } // Handle the case that the removed page was the active one. if (page == activePage_) { activePage_ = NULL; // Determine the new page to show: // 1. The page immediately above, if any // 2. The page immediately below, if any // 3. The list is empty, don't show any page if (!pageList_.isEmpty()) { if (itr == pageList_.begin()) (*itr)->showWidget(); else (*(--itr))->showWidget(); } } } } } kscope-1.9.4/app/addfilesdialog.h0000644000175000001440000000325711156714354016072 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __KSCOPE_ADDFILESDIALOG_H__ #define __KSCOPE_ADDFILESDIALOG_H__ #include #include #include "ui_addfilesdialog.h" namespace KScope { namespace App { /** * A dialogue used to select files to be added to a project. * @author Elad Lahav */ class AddFilesDialog : public QDialog, public Ui::AddFilesDialog { Q_OBJECT public: AddFilesDialog(QWidget* parent = NULL); ~AddFilesDialog(); void fileList(QStringList&) const; protected slots: void addFiles(); void addDir(); void addTree(); void loadFilter(); void saveFilter(); void deleteSelectedFiles(); private: bool getFiles(QFileDialog::FileMode, QStringList&); void addTree(bool); }; } } #endif // __KSCOPE_ADDFILESDIALOG_H__ kscope-1.9.4/app/actions.cpp0000644000175000001440000003245511156714354015134 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "actions.h" #include "mainwindow.h" #include "editorcontainer.h" #include "queryresultdock.h" namespace KScope { namespace App { /** * Class constructor. * @param Pointer to the main window */ Actions::Actions(MainWindow* parent) : QObject(parent) { } /** * Class destructor. */ Actions::~Actions() { } /** * Creates the actions. * Must be called after the main window's child widgets have been created. */ void Actions::setup() { QMenu* menu; QAction* action; // File menu. menu = mainWnd()->menuBar()->addMenu(tr("&File")); // Create a new file. action = new QAction(tr("&New"), this); action->setShortcut(tr("Ctrl+N")); action->setStatusTip(tr("New file")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(newFile())); menu->addAction(action); // Open an existing file. action = new QAction(tr("&Open"), this); action->setShortcut(tr("Ctrl+O")); action->setStatusTip(tr("Open existing file")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(openFile())); menu->addAction(action); // Close all open files. action = new QAction(tr("Close &All"), this); action->setStatusTip(tr("Close all open files")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(closeAll())); action->setEnabled(false); connect(mainWnd()->editCont_, SIGNAL(hasActiveEditor(bool)), action, SLOT(setEnabled(bool))); menu->addAction(action); menu->addSeparator(); // Exit the application. action = new QAction(tr("&Quit"), this); action->setShortcut(tr("Alt+F4")); action->setStatusTip(tr("Exit the application")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(close())); menu->addAction(action); // Edit menu. menu = mainWnd()->menuBar()->addMenu(tr("&Edit")); mainWnd()->editCont_->initActions(menu); // View menu. menu = mainWnd()->menuBar()->addMenu(tr("&View")); // Exclusive group for setting the editor view mode. QActionGroup* viewModeGroup = new QActionGroup(this); connect(viewModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(setEditorViewMode(QAction*))); // Display editors as sub-windows. action = new QAction(tr("&Sub-Window Mode"), this); action->setStatusTip(tr("Display editors as sub-windows")); action->setCheckable(true); action->setChecked(mainWnd()->editCont_->viewMode() == QMdiArea::SubWindowView); action->setData(QMdiArea::SubWindowView); menu->addAction(action); viewModeGroup->addAction(action); // Display editors as tabs. action = new QAction(tr("&Tabbed Mode"), this); action->setStatusTip(tr("Display editors as tabs")); action->setCheckable(true); action->setChecked(mainWnd()->editCont_->viewMode() == QMdiArea::TabbedView); action->setData(QMdiArea::TabbedView); menu->addAction(action); viewModeGroup->addAction(action); menu->addSeparator(); // Show/hide the query dock. menu->addAction(mainWnd()->queryDock_->toggleViewAction()); // A group for project actions requiring an open project. // Only enabled when there is an active project. QActionGroup* projectGroup = new QActionGroup(this); connect(ProjectManager::signalProxy(), SIGNAL(hasProject(bool)), projectGroup, SLOT(setEnabled(bool))); projectGroup->setEnabled(false); // Navigate menu. // Enabled only when there is an active project. menu = mainWnd()->menuBar()->addMenu(tr("&Navigate")); // Go to the next location in the navigation history. action = new QAction(tr("Next &Location"), this); action->setShortcut(tr("Alt+Right")); action->setStatusTip(tr("Next location in navigation history")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(gotoNextLocation())); menu->addAction(action); projectGroup->addAction(action); // Go to the previous location in the navigation history. action = new QAction(tr("Previous L&ocation"), this); action->setShortcut(tr("Alt+Left")); action->setStatusTip(tr("Previous location in navigation history")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(gotoPrevLocation())); menu->addAction(action); projectGroup->addAction(action); // Select the next query result. action = new QAction(tr("Next &Result"), this); action->setShortcut(tr("Alt+Down")); action->setStatusTip(tr("Select the next query result")); connect(action, SIGNAL(triggered()), mainWnd()->queryDock_, SLOT(selectNextResult())); menu->addAction(action); projectGroup->addAction(action); // Select the previous query result. action = new QAction(tr("Previous R&esult"), this); action->setShortcut(tr("Alt+Up")); action->setStatusTip(tr("Select the previous query result")); connect(action, SIGNAL(triggered()), mainWnd()->queryDock_, SLOT(selectPrevResult())); menu->addAction(action); projectGroup->addAction(action); menu->addSeparator(); // Browse location history. action = new QAction(tr("&History"), this); action->setShortcut(tr("Ctrl+H")); action->setStatusTip(tr("rowse location history")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(browseHistory())); menu->addAction(action); projectGroup->addAction(action); // Project menu. menu = mainWnd()->menuBar()->addMenu(tr("&Project")); // Create a new project. action = new QAction(tr("&New..."), this); action->setStatusTip(tr("New project")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(newProject())); menu->addAction(action); // Open an existing project. action = new QAction(tr("&Open..."), this); action->setShortcut(tr("Ctrl+P")); action->setStatusTip(tr("Open project")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(openProject())); menu->addAction(action); menu->addSeparator(); // Manage project files. action = new QAction(tr("&Files..."), this); action->setShortcut(tr("Ctrl+Shift+O")); action->setStatusTip(tr("Manage project files")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(projectFiles())); menu->addAction(action); projectGroup->addAction(action); // View/edit project parameters. action = new QAction(tr("&Properties..."), this); action->setStatusTip(tr("View/edit project parameters")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(projectProperties())); menu->addAction(action); projectGroup->addAction(action); // Build the project's database. action = new QAction(tr("&Build Database"), this); action->setShortcut(tr("Ctrl+B")); action->setStatusTip(tr("Build the project database")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(buildProject())); menu->addAction(action); projectGroup->addAction(action); menu->addSeparator(); // Close the active project. action = new QAction(tr("&Close"), this); action->setStatusTip(tr("Close the active project")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(closeProject())); menu->addAction(action); projectGroup->addAction(action); // Query menu. // Enabled only when there is an active project. menu = mainWnd()->menuBar()->addMenu(tr("&Query")); // Quick definition. // Needs an active editor to be enabled. action = new QAction(tr("&Quick Definition"), this); action->setShortcut(tr("Ctrl+]")); action->setStatusTip(tr("Find symbol definition")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(quickDefinition())); action->setEnabled(false); connect(mainWnd()->editCont_, SIGNAL(hasActiveEditor(bool)), action, SLOT(setEnabled(bool))); menu->addAction(action); projectGroup->addAction(action); menu->addSeparator(); // A group for all query actions. // Handles all of these actions with a single slot. QActionGroup* queryGroup = new QActionGroup(this); connect(queryGroup, SIGNAL(triggered(QAction*)), this, SLOT(query(QAction*))); // Query references. action = new QAction(tr("&References"), this); action->setShortcut(tr("Ctrl+0")); action->setStatusTip(tr("Find all symbol references")); action->setData(Core::Query::References); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Query definition. action = new QAction(tr("&Definition"), this); action->setShortcut(tr("Ctrl+1")); action->setStatusTip(tr("Find symbol definition")); action->setData(Core::Query::Definition); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Query called functions. action = new QAction(tr("&Called Functions"), this); action->setShortcut(tr("Ctrl+2")); action->setStatusTip(tr("Show functions called from function")); action->setData(Core::Query::CalledFunctions); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Query calling functions. action = new QAction(tr("C&alling Functions"), this); action->setShortcut(tr("Ctrl+3")); action->setStatusTip(tr("Find functions calling function")); action->setData(Core::Query::CallingFunctions); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Query text. action = new QAction(tr("&Text"), this); action->setShortcut(tr("Ctrl+4")); action->setStatusTip(tr("Find text in files")); action->setData(Core::Query::Text); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Find file. action = new QAction(tr("&File"), this); action->setShortcut(tr("Ctrl+7")); action->setStatusTip(tr("Find a file")); action->setData(Core::Query::FindFile); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Find including files. action = new QAction(tr("&Including Files"), this); action->setShortcut(tr("Ctrl+8")); action->setStatusTip(tr("Find files #including a given file")); action->setData(Core::Query::IncludingFiles); menu->addAction(action); projectGroup->addAction(action); queryGroup->addAction(action); // Show local tags. action = new QAction(tr("Local &Tags"), this); action->setShortcut(tr("Ctrl+T")); action->setStatusTip(tr("List tags in the current file")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(showLocalTags())); connect(mainWnd()->editCont_, SIGNAL(hasActiveEditor(bool)), action, SLOT(setEnabled(bool))); action->setEnabled(false); menu->addAction(action); projectGroup->addAction(action); menu->addSeparator(); // Call tree. action = new QAction(tr("Call &Tree"), this); action->setShortcut(tr("Ctrl+\\")); action->setStatusTip(tr("Create a call tree")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(promptCallTree())); menu->addAction(action); // Settings menu. menu = mainWnd()->menuBar()->addMenu(tr("&Settings")); // Editor configuration. action = new QAction(tr("Configure &Editor"), this); action->setStatusTip(tr("Modify editor settings")); connect(action, SIGNAL(triggered()), mainWnd()->editCont_, SLOT(configEditor())); menu->addAction(action); // Engine configuration. action = new QAction(tr("Configure E&ngines"), this); action->setStatusTip(tr("Manage engine configuration")); connect(action, SIGNAL(triggered()), mainWnd(), SLOT(configEngines())); menu->addAction(action); // Dynamically-created Window menu. wndMenu_ = mainWnd()->menuBar()->addMenu(tr("&Window")); connect(wndMenu_, SIGNAL(aboutToShow()), this, SLOT(showWindowMenu())); // Help menu. menu = mainWnd()->menuBar()->addMenu(tr("&Help")); action = new QAction(tr("&About..."), this); action->setStatusTip(tr("Show application information")); connect(action, SIGNAL(triggered()), qApp, SLOT(about())); menu->addAction(action); } /** * A common handler for query menu actions. * @param action The triggered action */ void Actions::query(QAction* action) { Core::Query::Type type; type = static_cast(action->data().toUInt()); mainWnd()->promptQuery(type); } /** * Constructs a sub-menu showing all open editor windows. * Called before the "Window" menu is shown. */ void Actions::showWindowMenu() { wndMenu_->clear(); mainWnd()->editCont_->populateWindowMenu(wndMenu_); } /** * Determines the view mode of the editor container. * This is a common handler to the "View->Sub-Window Mode" and "View->Tabbed * Mode" actions. * @param action The triggerred action */ void Actions::setEditorViewMode(QAction* action) { QMdiArea::ViewMode mode = static_cast(action->data().toUInt()); mainWnd()->editCont_->setViewMode(mode); } /** * @return Pointer to the main window */ MainWindow* Actions::mainWnd() { return static_cast(parent()); } } // namespace App } // namespace KScope kscope-1.9.4/app/mainwindow.h0000644000175000001440000000512011156714354015302 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_MAINWINDOW_H #define __APP_MAINWINDOW_H #include #include #include "actions.h" #include "buildprogress.h" #include "editor/editor.h" class QCloseEvent; namespace KScope { namespace App { class EditorContainer; class QueryResultDock; class QueryDialog; /** * KScope's main window. * This is an MDI-style main window. The central area is used for viewing and * editing source files, while docks are used for browsing information (e.g., * engine query results). * @author Elad Lahav */ class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); ~MainWindow(); public slots: void promptQuery(Core::Query::Type type = Core::Query::References); void quickDefinition(); void promptCallTree(); void buildProject(); void openFile(const QString&); // Action handlers. void newProject(); void openProject(); bool closeProject(); void projectFiles(); void projectProperties(); void configEngines(); protected: virtual void closeEvent(QCloseEvent*); private: friend class Actions; /** * Main menu commands. */ Actions actions_; /** * Manages the editor widgets. */ EditorContainer* editCont_; /** * Holds query result views in a docked widget. */ QueryResultDock* queryDock_; /** * Used to prompt for query information. */ QueryDialog* queryDlg_; /** * Provides progress information on an engine's build process. */ BuildProgress buildProgress_; void readSettings(); void writeSettings(); void setWindowTitle(bool); private slots: void projectOpenedClosed(bool); }; } // namespace App } // namespace KScope #endif // __APP_MAINWINDOW_H kscope-1.9.4/app/projectmanager.h0000644000175000001440000000570611156714354016141 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_PROJECTMANAGER_H__ #define __APP_PROJECTMANAGER_H__ #include #include #include "application.h" namespace KScope { namespace App { /** * Proxy for emitting signals from the ProjectManager class. * The reason is to allow ProjectManager to use only static members, and not * be a Q_OBJECT (which would limit templating). * @author Elad Lahav */ class ProjectManagerSignals : public QObject { Q_OBJECT signals: void hasProject(bool has); void buildProject(); private: ProjectManagerSignals() : QObject() {} void emitHasProject(bool has) { emit hasProject(has); } void emitBuildProject() { emit buildProject(); } friend class ProjectManager; }; /** * Provides the active project for the application. * Maintains a ProjectBase object, which is the one and only active project in * the application. Also, provides safe access to the engine and code base * objects of the project. * @author Elad Lahav */ class ProjectManager { public: static bool hasProject() { return proj_ != NULL; } static const Core::ProjectBase* project(); static Core::Engine& engine(); static Core::Codebase& codebase(); static const ProjectManagerSignals* signalProxy(); template static void load(const QString& projPath) { // Do not load if another project is currently loaded. if (proj_) return; // Create and open a project. try { proj_ = new ProjectT(projPath); proj_->open(new OpenCallback()); } catch (Core::Exception* e) { throw e; } // Save the project path. Application::settings().addRecentProject(projPath, proj_->name()); } static void updateConfig(Core::ProjectBase::Params&); static void close(); private: static Core::ProjectBase* proj_; static ProjectManagerSignals signals_; static void finishLoad(); struct OpenCallback : public Core::Callback<> { void call() { ProjectManager::finishLoad(); delete this; } }; }; } // namespace App } // namespace KScope #endif // __APP_PROJECTMANAGER_H__ kscope-1.9.4/app/app.pro0000644000175000001440000000261411156714354014264 0ustar elahavusersinclude(../config) TEMPLATE = app TARGET = kscopeapp DEPENDPATH += ". ../core ../cscope ../editor" # Input SOURCES += openprojectdialog.cpp \ settings.cpp \ session.cpp \ projectmanager.cpp \ projectdialog.cpp \ projectfilesdialog.cpp \ stackwidget.cpp \ main.cpp \ mainwindow.cpp \ actions.cpp \ application.cpp \ querydialog.cpp \ editorcontainer.cpp \ queryresultdock.cpp \ queryresultdialog.cpp \ addfilesdialog.cpp \ configenginesdialog.cpp HEADERS += openprojectdialog.h \ settings.h \ session.h \ queryview.h \ strings.h \ locationhistory.h \ projectmanager.h \ projectfilesdialog.h \ stackwidget.h \ mainwindow.h \ actions.h \ application.h \ querydialog.h \ editorcontainer.h \ queryresultdock.h \ queryresultdialog.h \ addfilesdialog.h \ projectdialog.h \ buildprogress.h \ version.h \ configenginesdialog.h FORMS += querydialog.ui \ queryresultdialog.ui \ stackpage.ui \ projectfilesdialog.ui \ addfilesdialog.ui \ projectdialog.ui \ configenginesdialog.ui \ openprojectdialog.ui INCLUDEPATH += .. \ $${QSCI_ROOT_PATH}/include/Qsci \ . LIBS += -L../core \ -lkscope_core \ -L../cscope \ -lkscope_cscope \ -L../editor \ -lkscope_editor RESOURCES = app.qrc target.path = $${INSTALL_PATH}/bin INSTALLS += target kscope-1.9.4/app/projectdialog.ui0000644000175000001440000001754711156714354016162 0ustar elahavusers ProjectDialog 0 0 479 335 Dialog 0 General Name: Root Path 0 ... Project Configuration Directory Use a named directory under the following path: true 0 ... Use a hidden directory under the root path Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok nameEdit_ rootPathEdit_ browseRootPathButton_ namedDirButton_ projectPathEdit_ browseProjectPathButton_ hiddenDirButton_ buttonBox configTabs_ buttonBox accepted() ProjectDialog accept() 236 305 157 183 buttonBox rejected() ProjectDialog reject() 304 305 286 183 browseProjectPathButton_ clicked() ProjectDialog browseProjectPath() 446 231 472 135 browseRootPathButton_ clicked() ProjectDialog browseRootPath() 445 94 470 105 namedDirButton_ toggled(bool) projectPathWidget_ setEnabled(bool) 406 192 413 207 projectPathEdit_ textChanged(QString) ProjectDialog updateProjectPath() 350 218 474 288 namedDirButton_ toggled(bool) ProjectDialog updateProjectPath() 68 184 1 191 rootPathEdit_ textChanged(QString) ProjectDialog updateProjectPath() 236 92 476 55 nameEdit_ textChanged(QString) ProjectDialog updateProjectPath() 161 58 474 23 browseRootPath() browseProjectPath() updateProjectPath() kscope-1.9.4/app/openprojectdialog.ui0000644000175000001440000001401311156714354017025 0ustar elahavusers OpenProjectDialog true 0 0 485 418 Open Project Path ... Recent Projects Qt::Horizontal 40 20 false Remove &New... Qt::Horizontal 40 20 false &Open true &Cancel pathEdit_ browseButton_ recentProjectsList_ removeProjectButton_ newButton_ openButton_ cancelButton_ cancelButton_ clicked() OpenProjectDialog reject() 427 393 281 394 newButton_ clicked() OpenProjectDialog newProject() 68 392 134 387 pathEdit_ textChanged(QString) OpenProjectDialog pathChanged(QString) 355 20 483 42 recentProjectsList_ itemSelectionChanged() OpenProjectDialog recentProjectSelected() 180 137 482 159 removeProjectButton_ clicked() OpenProjectDialog removeProject() 439 336 480 351 browseButton_ clicked() OpenProjectDialog browse() 462 21 482 13 openButton_ clicked() OpenProjectDialog accept() 356 399 298 374 newProject() pathChanged(QString) recentProjectSelected() removeProject() browse() kscope-1.9.4/app/querydialog.cpp0000644000175000001440000000754411156714354016022 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include "querydialog.h" #include "strings.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ QueryDialog::QueryDialog(QWidget* parent) : QDialog(parent), Ui::QueryDialog() { setupUi(this); } /** * Class destructor. */ QueryDialog::~QueryDialog() { } /** * Displays a modal dialogue. * @param defType Default query type * @param typeList The types to show */ int QueryDialog::exec(Core::Query::Type defType, const TypeList& typeList) { // Prepare the query type combo box. typeCombo_->clear(); if (typeList.size() > 0) { foreach (Core::Query::Type type, typeList) typeCombo_->addItem(Strings::toString(type), type); } else { // Create a list with all supported query types. TypeList typeList; typeList << Core::Query::Text << Core::Query::References << Core::Query::Definition << Core::Query::CalledFunctions << Core::Query::CallingFunctions << Core::Query::FindFile << Core::Query::IncludingFiles; foreach (Core::Query::Type type, typeList) typeCombo_->addItem(Strings::toString(type), type); } // Select the default type. typeCombo_->setCurrentIndex(typeCombo_->findData(defType)); return QDialog::exec(); } /** * @return The text in the pattern editor */ QString QueryDialog::pattern() { return patternCombo_->lineEdit()->text(); } /** * @param pattern Initial text for the pattern editor */ void QueryDialog::setPattern(const QString& pattern) { patternCombo_->lineEdit()->setText(pattern); patternCombo_->lineEdit()->selectAll(); } /** * @return The selected query type. */ Core::Query::Type QueryDialog::type() { int index; QVariant data; index = typeCombo_->currentIndex(); if (index == -1) return Core::Query::References; data = typeCombo_->itemData(index); return static_cast(data.toUInt()); } /** * Deletes all items in the pattern combo-box. */ void QueryDialog::clear() { patternCombo_->clear(); } /** * Called when the user clicks the "OK" button. * Removes all white space from before and after the entered text. */ void QueryDialog::accept() { // Get a trimmed version of the current text. QString text = patternCombo_->lineEdit()->text().trimmed(); if (text.isEmpty()) { QMessageBox::warning(this, tr("Invalid Pattern"), tr("Please enter a non-empty pattern")); return; } // Remove an existing copy of the pattern. int i = patternCombo_->findText(text); if (i >= 0) { patternCombo_->removeItem(i); } // Add to the top of the history list. patternCombo_->insertItem(i, text); // Make sure the list does not exceed 20 items. while (patternCombo_->count() >= 20) patternCombo_->removeItem(patternCombo_->count() - 1); // Set as the current text. patternCombo_->lineEdit()->setText(text); QDialog::accept(); } } // namespace App } // namespace KScope kscope-1.9.4/app/buildprogress.h0000644000175000001440000000736211156714354016024 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_BUILDPROGRESS_H__ #define __APP_BUILDPROGRESS_H__ #include #include #include #include namespace KScope { namespace App { /** * Provides progress information on a build process. * Information is displayed in either a modal dialogue, or a progress-bar * widget (which can be embedded in other widgets, such as a status bar). * @author Elad Lahav */ class BuildProgress : public QObject, public Core::Engine::Connection { Q_OBJECT public: /** * Class constructor. */ BuildProgress() : Core::Engine::Connection(), dlg_(NULL), bar_(NULL) {} /** * Class destructor. */ ~BuildProgress() {} /** * Creates a display widget. * @param useDialog true to create a dialogue, false for a progress bar * @param parent The parent widget to use * @return The created widget */ QWidget* init(bool useDialog, QWidget* parent) { if (!useDialog) { bar_ = new Core::ProgressBar(parent); connect(bar_, SIGNAL(cancelled()), this, SLOT(stopBuild())); bar_->setFrameShape(QFrame::NoFrame); bar_->setProgress(0, 0); bar_->setLabel(tr("Initialising...")); bar_->show(); return bar_; } dlg_ = new QProgressDialog(parent); connect(dlg_, SIGNAL(canceled()), this, SLOT(stopBuild())); dlg_->setWindowTitle(tr("Building Project")); dlg_->setLabelText(tr("Initialising...")); dlg_->setModal(true); dlg_->show(); return dlg_; } /** * Does nothing, as no data is expected from a build process. * @param locList ignored */ void onDataReady(const Core::LocationList& locList) { (void)locList; } /** * Deletes the widget when the build process ends. */ void onFinished() { qDebug() << __func__; if (dlg_) delete dlg_; if (bar_) delete bar_; dlg_ = NULL; bar_ = NULL; } /** * Deletes the widget when the build process ends. */ void onAborted() { qDebug() << __func__; if (dlg_) delete dlg_; if (bar_) delete bar_; dlg_ = NULL; bar_ = NULL; } /** * Updates progress information. * @param text Progress message * @param cur Current value * @param total Expected final value */ void onProgress(const QString& text, uint cur, uint total) { qDebug() << __func__ << text << cur << total; if (dlg_) { dlg_->setRange(0, total); dlg_->setValue(cur); dlg_->setLabelText(text); } if (bar_) { bar_->setProgress(cur, total); bar_->setLabel(text); } } private: /** * A progress dialogue. */ QProgressDialog* dlg_; /** * A progress-bar. */ Core::ProgressBar* bar_; private slots: /** * Stops the build process when the "Cancel" button is clicked in either the * dialogue or the progress-bar. */ void stopBuild() { stop(); } }; } // namespace App } // namespace KScope #endif // __APP_BUILDPROGRESS_H__ kscope-1.9.4/app/projectmanager.cpp0000644000175000001440000000561411156714354016472 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "projectmanager.h" namespace KScope { namespace App { Core::ProjectBase* ProjectManager::proj_ = NULL; ProjectManagerSignals ProjectManager::signals_; const Core::ProjectBase* ProjectManager::project() { if (proj_ == NULL) throw new Core::Exception("No project is currently loaded"); return proj_; } Core::Engine& ProjectManager::engine() { if (proj_ == NULL) throw Core::Exception("No project is currently loaded"); Core::Engine* engine = proj_->engine(); if (engine == NULL) throw new Core::Exception("No engine is available"); return *engine; } Core::Codebase& ProjectManager::codebase() { if (proj_ == NULL) throw new Core::Exception("No project is currently loaded"); Core::Codebase* cbase = proj_->codebase(); if (cbase == NULL) throw new Core::Exception("No engine is available"); return *cbase; } const ProjectManagerSignals* ProjectManager::signalProxy() { return &signals_; } void ProjectManager::updateConfig(Core::ProjectBase::Params& params) { // Make sure a project is loaded. if (proj_ == NULL) throw new Core::Exception("No project is currently loaded"); // Update project parameters. try { proj_->updateConfig(params); } catch (Core::Exception* e) { throw e; } } /** * Closes the current project. */ void ProjectManager::close() { // Nothing to do if there is no open project. if (proj_ == NULL) return; // Close the project. proj_->close(); delete proj_; proj_ = NULL; // Notify that the project is closed. signals_.emitHasProject(false); } void ProjectManager::finishLoad() { // Signal the availability of a project. ProjectManager::signals_.emitHasProject(true); // Does the database need to be rebuilt? Core::Engine* engine = proj_->engine(); if (engine) { if ((engine->status() == Core::Engine::Build) || (engine->status() == Core::Engine::Rebuild)) { signals_.emitBuildProject(); } } } } // namespace App } // namespace KScope kscope-1.9.4/app/version.h0000644000175000001440000000420711156714354014620 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_VERSION_H__ #define __APP_VERSION_H__ namespace KScope { namespace App { /** * Generates version information. * @todo Would like to automate generation of version from external source * (e.g., SVN). * @author Elad Lahav */ template struct Version { /** * Major version number. */ static const int major_ = Major; /** * Minor version number. */ static const int minor_ = Minor; /** * Revision number. */ static const int revision_ = Revision; /** * Translates the version numbers into a string. * The string is of the form "MAJOR.MINOR.REVISION (BUILD_DATE)" * @return The formatted version */ static QString toString() { return QString("%1.%2.%3 (Built %4)").arg(major_).arg(minor_) .arg(revision_).arg(__DATE__); } /** * Determines whether the current version is an alpha/beta/RC release. * This is signified by an odd minor number. */ static bool isDevel() { return (minor_ & 0x1) == 1; } }; /** * Specifies the application version. */ typedef Version<1, 9, 4> AppVersion; } // namespace App } // namespace KScope #endif // __APP_VERSION_H__ kscope-1.9.4/app/projectfilesdialog.cpp0000644000175000001440000000451411156714354017340 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "application.h" #include "projectfilesdialog.h" #include "addfilesdialog.h" #include "projectmanager.h" namespace KScope { namespace App { ProjectFilesDialog::ProjectFilesDialog(QWidget* parent) : QDialog(parent), Ui::ProjectFilesDialog() { setupUi(this); try { const Core::ProjectBase* proj = ProjectManager::project(); const Core::Codebase* codebase = &ProjectManager::codebase(); Core::CodebaseModel* model = new Core::CodebaseModel(codebase, proj->rootPath(), this); view_->setModel(model); } catch (Core::Exception* e) { e->showMessage(); delete e; } } ProjectFilesDialog::~ProjectFilesDialog() { } void ProjectFilesDialog::accept() { // Get all files from the model. Core::CodebaseModel* model = static_cast(view_->model()); QStringList fileList; model->getFiles(fileList); // Update the code base. try { ProjectManager::codebase().setFiles(fileList); } catch (Core::Exception* e) { e->showMessage(); delete e; } QDialog::accept(); } void ProjectFilesDialog::addFiles() { AddFilesDialog dlg(this); if (dlg.exec() == QDialog::Accepted) { QStringList fileList; dlg.fileList(fileList); Core::CodebaseModel* model = static_cast(view_->model()); model->addFiles(fileList); } } void ProjectFilesDialog::removeFiles() { // TODO: Implement! } } } kscope-1.9.4/app/projectdialog.h0000644000175000001440000000626511156714354015767 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_PROJECTDIALOG_H__ #define __APP_PROJECTDIALOG_H__ #include #include #include #include "ui_projectdialog.h" namespace KScope { namespace App { /** * Allows the configuration of project properties. * Used either to create a new project, or to modify an existing one. * @author Elad Lahav */ class ProjectDialog : public QDialog, public Ui::ProjectDialog { Q_OBJECT public: ProjectDialog(QWidget* parent = NULL); ~ProjectDialog(); /** * @param proj The project from which to read parameters, NULL for a new * project */ template void setParamsForProject(const ProjectT* proj) { if (proj) { // Display properties for an existing project. setWindowTitle(tr("Project Properties")); projectPathGroup_->setEnabled(false); // Get the current project properties. Core::ProjectBase::Params params; proj->getCurrentParams(params); // Update dialogue controls. nameEdit_->setText(params.name_); rootPathEdit_->setText(params.rootPath_); projectPathLabel_->setText(params.projPath_); } else { // New project dialogue. setWindowTitle(tr("New Project")); projectPathEdit_->setText(QDir::home().path()); } // Add a project-specific configuration page. confWidget_ = Core::ProjectConfig::createConfigWidget(proj, this); if (confWidget_) configTabs_->addTab(confWidget_, confWidget_->windowTitle()); } /** * Fills a project parameters structure with values reflecting the current * selections in the dialogue. * @param params The structure to fill */ template void getParams(Core::ProjectBase::Params& params) { // Fill parameters from the main page. params.projPath_ = projectPathLabel_->text(); params.name_ = nameEdit_->text(); params.rootPath_ = rootPathEdit_->text(); // Get parameters from the project-specific configuration page. if (confWidget_) { Core::ProjectConfig ::paramsFromWidget(confWidget_, params); } } protected slots: void browseRootPath(); void browseProjectPath(); void updateProjectPath(); private: QWidget* confWidget_; }; } // namespace App } // namespace KScope #endif // __APP_PROJECTDIALOG_H__ kscope-1.9.4/app/queryresultdialog.ui0000644000175000001440000000256611156714354017113 0ustar elahavusers QueryResultDialog 0 0 570 410 Query Results Qt::Horizontal QDialogButtonBox::Close KScope::Core::QueryView QTreeView
queryview.h
buttonBox rejected() QueryResultDialog reject() 444 383 566 355
kscope-1.9.4/app/stackpage.ui0000644000175000001440000000606411156714354015266 0ustar elahavusers StackPage 0 0 635 662 Form 0 0 Qt::Horizontal 0 0 75 true TextLabel Qt::PlainText Qt::Horizontal 40 20 0 0 Show page Show :/images/show.png:/images/show.png true Close page X :/images/close.png:/images/close.png Qt::ToolButtonIconOnly true kscope-1.9.4/app/querydialog.ui0000644000175000001440000000646711156714354015660 0ustar elahavusers QueryDialog 0 0 465 121 Query Pattern Query 0 0 0 0 true Qt::Horizontal Qt::Horizontal 151 20 &OK true &Cancel patternCombo_ typeCombo_ okButton_ cancelButton_ okButton_ clicked() QueryDialog accept() 281 145 310 84 cancelButton_ clicked() QueryDialog reject() 382 153 436 99 kscope-1.9.4/app/queryview.h0000644000175000001440000000365011156714354015174 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_QUERYVIEW_H__ #define __APP_QUERYVIEW_H__ #include #include #include "projectmanager.h" namespace KScope { namespace App { /** * A specialisation of Core::QueryView, which uses the current engine, as * supplied by the project manager. * @author Elad Lahav */ class QueryView : public Core::QueryView { Q_OBJECT public: /** * Class constructor. * @param parent Parent widget * @param type Whether to create a list or a tree view */ QueryView(QWidget* parent, Type type = List) : Core::QueryView(parent, type) {} /** * Class destructor. */ ~QueryView() {} protected: /** * @return The engine supplied by the project manager * @throw Exception */ Core::Engine* engine() { Core::Engine* eng; try { eng = &ProjectManager::engine(); } catch (Core::Exception* e) { throw e; } return eng; } }; } // namespace App } // namespace KScope #endif // __APP_QUERYVIEW_H__ kscope-1.9.4/app/session.cpp0000644000175000001440000001062111156714354015146 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "session.h" #include "projectmanager.h" namespace KScope { namespace App { /** * Class constructor. * @param path The path of the configuration directory */ Session::Session(const QString& path) : path_(path), queryViewDoc_("QueryViews") { } /** * Class destructor. */ Session::~Session() { } /** * Reads session information from the configuration file. */ void Session::load() { QSettings settings(configFile(), QSettings::IniFormat); // Get a list of files being edited, along with the location of the // cursor on each one. int size = settings.beginReadArray("Editors"); for (int i = 0; i < size; i++) { settings.setArrayIndex(i); Core::Location loc; loc.file_ = settings.value("Path").toString(); loc.line_ = settings.value("Line").toUInt(); loc.column_ = settings.value("Column").toUInt(); editorList_.append(loc); } settings.endArray(); // Get the path of the active editor. activeEditor_ = settings.value("ActiveEditor").toString(); maxActiveEditor_ = settings.value("MaxActiveEditor", false).toBool(); // Load the query XML file. QFile xmlFile(queryViewFile()); if (xmlFile.open(QIODevice::ReadOnly)) queryViewDoc_.setContent(xmlFile.readAll()); } /** * Writes session information to the configuration file. */ void Session::save() { QSettings settings(configFile(), QSettings::IniFormat); // Store a list of files being edited, along with the location of the // cursor on each one. settings.beginWriteArray("Editors"); for (int i = 0; i < editorList_.size(); i++) { settings.setArrayIndex(i); const Core::Location& loc = editorList_.at(i); settings.setValue("Path", loc.file_); settings.setValue("Line", loc.line_); settings.setValue("Column", loc.column_); } settings.endArray(); // Store other information on the editor container. settings.setValue("ActiveEditor", activeEditor_); settings.setValue("MaxActiveEditor", maxActiveEditor_); // Save the query view XML document. QFile xmlFile(queryViewFile()); if (xmlFile.open(QIODevice::WriteOnly)) xmlFile.write(queryViewDoc_.toByteArray()); } /** * Creates an XML representation of a query view. * The representation is rooted at a "QueryView" element, which holds a * "Query" element for query information, and "Location" elements for query * results. * @param view */ void Session::addQueryView(const QueryView* view) { // Get the root element. // Create one if it does not exists. QDomElement root = queryViewDoc_.documentElement(); if (root.isNull()) { root = queryViewDoc_.createElement("Queries"); queryViewDoc_.appendChild(root); } // Put location information under the element. QDomElement viewElem = queryViewDoc_.createElement("QueryView"); root.appendChild(viewElem); view->toXML(queryViewDoc_, viewElem); } /** * Creates an iterator that is used for loading query views from an XML * representation. * Once an iterator has been created, a view object can use its load() method * to get the query information and locations. * @return */ Session::QueryViewIterator Session::beginQueryIteration() const { QueryViewIterator itr; QDomElement root = queryViewDoc_.documentElement(); itr.queryNodeList_ = root.elementsByTagName("QueryView"); itr.listPos_ = -1; ++itr; return itr; } void Session::QueryViewIterator::load(QueryView* view) { // Ensure the iterator's XML element is valid. if (!elem_.isNull()) view->fromXML(elem_); } } // namespace App } // namespace KScope kscope-1.9.4/app/editorcontainer.h0000644000175000001440000000630411156714354016324 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_EDITORCONTAINER_H #define __APP_EDITORCONTAINER_H #include #include #include #include #include #include #include #include #include #include "locationhistory.h" #include "session.h" namespace KScope { namespace App { /** * Manages editor windows. * This is the central widget of the main window. It contains and manages all * open editor windows in an MDI-style. * @author Elad Lahav */ class EditorContainer : public QMdiArea { Q_OBJECT public: EditorContainer(QMainWindow* parent); ~EditorContainer(); void initActions(QMenu*); void populateWindowMenu(QMenu*) const; bool canClose(); void saveSession(Session&); void loadSession(Session&); void clearHistory(); inline Editor::Editor* currentEditor() { return editorFromWindow(currentSubWindow()); } public slots: void newFile(); void openFile(); void configEditor(); void gotoLocation(const Core::Location&); void gotoNextLocation(); void gotoPrevLocation(); void showLocalTags(); void browseHistory(); void closeAll(); signals: void hasActiveEditor(bool has); private: QMdiSubWindow* currentWindow_; QMap fileMap_; uint newFileIndex_; LocationHistory history_; bool windowActivationBlocked_; Editor::Config config_; Editor::Actions actions_; /** * Displays the current cursor position in the status bar. */ QLabel* cursorPositionLabel_; /** * Displays the edit mode for the current editor. */ QLabel* editModeLabel_; bool gotoLocationInternal(const Core::Location&); Editor::Editor* findEditor(const QString&); Editor::Editor* createEditor(const QString&); void blockWindowActivation(bool); static inline Editor::Editor* editorFromWindow(QMdiSubWindow* window) { if (!window) return NULL; return static_cast(window->widget()); } private slots: void handleWindowAction(QAction*); void windowActivated(QMdiSubWindow*); void removeEditor(const QString&); void remapEditor(const QString&, const QString&); void showCursorPosition(int, int); void showEditMode(Editor::ViScintilla::EditMode); }; } // namespace App } // namespace KScope #endif // __APP_EDITORCONTAINER_H kscope-1.9.4/app/app.qrc0000644000175000001440000000025411156714354014247 0ustar elahavusers images/kscope.png images/close.png images/show.png kscope-1.9.4/app/application.h0000644000175000001440000000350011156714354015431 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_APPLICATION_H #define __APP_APPLICATION_H #include #include "settings.h" namespace KScope { namespace App { class MainWindow; /** * The KScope application. * Runs the event loop and maintains the active project. * @author Elad Lahav */ class Application : public QApplication { Q_OBJECT public: Application(int&, char**); ~Application(); enum Event { AppInitEvent = QEvent::User }; int run(); static Settings& settings() { return *(static_cast(qApp)->settings_); } public slots: void about(); protected: void customEvent(QEvent*); private: /** * The main window. */ MainWindow* mainWnd_; Settings* settings_; void init(); void setupEngines(); }; inline Application* theApp() { return static_cast(qApp); } } // namespace App } // namespace KScope #endif // __APP_APPLICATION_H kscope-1.9.4/app/mainwindow.cpp0000644000175000001440000003361111156714354015643 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include #include #include "mainwindow.h" #include "editorcontainer.h" #include "querydialog.h" #include "queryresultdock.h" #include "projectmanager.h" #include "queryresultdialog.h" #include "session.h" #include "projectdialog.h" #include "openprojectdialog.h" #include "projectfilesdialog.h" #include "configenginesdialog.h" namespace KScope { namespace App { /** * Class constructor. */ MainWindow::MainWindow() : QMainWindow(), actions_(this) { // Set the window title. // This changes whenever a project is opened/closed. setWindowTitle(false); // The main window icon. setWindowIcon(QIcon(":/images/kscope")); // Create the central widget (the editor manager). editCont_ = new EditorContainer(this); setCentralWidget(editCont_); // Create the query result dock. queryDock_ = new QueryResultDock(this); addDockWidget(Qt::RightDockWidgetArea, queryDock_); connect(queryDock_, SIGNAL(locationRequested(const Core::Location&)), editCont_, SLOT(gotoLocation(const Core::Location&))); // Create the query dialogue. queryDlg_ = new QueryDialog(this); // Create a status bar. statusBar(); // Initialise actions. // The order is important: make sure the child widgets are created BEFORE // calling setup(). actions_.setup(); // Apply saved window settings. readSettings(); // Perform actions when a project is opened or closed. connect(ProjectManager::signalProxy(), SIGNAL(hasProject(bool)), this, SLOT(projectOpenedClosed(bool))); // Rebuild the project when signalled by the project manager. connect(ProjectManager::signalProxy(), SIGNAL(buildProject()), this, SLOT(buildProject())); } /** * Class destrutor. */ MainWindow::~MainWindow() { } /** * Prompts the user for query information, and starts a query with the entered * parameters. * @param type The default query type to use */ void MainWindow::promptQuery(Core::Query::Type type) { queryDlg_->setWindowTitle(tr("Query")); // Get the default pattern from the text under the cursor on the active // editor (if any). Editor::Editor* editor = editCont_->currentEditor(); if (editor) queryDlg_->setPattern(editor->currentSymbol()); // Prompt the user. if (queryDlg_->exec(type) != QDialog::Accepted) return; // Start a query with results shown in a view inside the query dock. queryDock_->query(Core::Query(queryDlg_->type(), queryDlg_->pattern()), false); } /** * Implements a definition query that does not display its results in the * query dock. * If the query results in a single location, this location is immediately * displayed in the editor container. Otherwise, the user is prompted for the * location, using a results dialogue. */ void MainWindow::quickDefinition() { QString symbol; // Get the default pattern from the text under the cursor on the active // editor (if any). Editor::Editor* editor = editCont_->currentEditor(); if (editor) symbol = editor->currentSymbol(); // Prompt for a symbol, if none is selected in the current editor. if (symbol.isEmpty()) { // Prompt for a symbol. queryDlg_->setWindowTitle(tr("Quick Definition")); QueryDialog::TypeList typeList; typeList << Core::Query::Definition; if (queryDlg_->exec(Core::Query::Definition, typeList) != QDialog::Accepted) { return; } // Get the symbol from the dialogue. symbol = queryDlg_->pattern(); if (symbol.isEmpty()) return; } // Create a query view dialogue. QueryResultDialog* dlg = new QueryResultDialog(this); dlg->setModal(true); // Automatically select a single result. Core::QueryView* view = dlg->view(); view->setAutoSelectSingleResult(true); // Forward selected locations to the editor container. connect(view, SIGNAL(locationRequested(const Core::Location&)), editCont_, SLOT(gotoLocation(const Core::Location&))); // Only show the dialogue if needed. connect(view, SIGNAL(needToShow()), dlg, SLOT(show())); try { // Run the query. Core::LocationModel* model = view->locationModel(); model->setRootPath(ProjectManager::project()->rootPath()); model->setColumns(ProjectManager::engine() .queryFields(Core::Query::Definition)); ProjectManager::engine().query(view, Core::Query(Core::Query::Definition, symbol)); } catch (Core::Exception* e) { e->showMessage(); delete e; } } /** * Prompts the user for a symbol to create a call-tree for. */ void MainWindow::promptCallTree() { queryDlg_->setWindowTitle(tr("Call Tree")); // Get the default pattern from the text under the cursor on the active // editor (if any). Editor::Editor* editor = editCont_->currentEditor(); if (editor) queryDlg_->setPattern(editor->currentSymbol()); // Prompt the user. QueryDialog::TypeList typeList; typeList << Core::Query::CalledFunctions << Core::Query::CallingFunctions; if (queryDlg_->exec(Core::Query::CalledFunctions, typeList) != QDialog::Accepted) { return; } // Start a query with results shown in a view inside the query dock. queryDock_->query(Core::Query(queryDlg_->type(), queryDlg_->pattern()), true); } /** * Starts a build process for the current project's engine. * Provides progress information in either a modal dialogue or a progress-bar * in the window's status bar. The modal dialogue is used for initial builds, * while the progress-bar is used for rebuilds. */ void MainWindow::buildProject() { try { // Create a build progress widget. if (ProjectManager::engine().status() == Core::Engine::Build) { buildProgress_.init(true, this); } else { QWidget* widget = buildProgress_.init(false, this); widget->setMaximumHeight(statusBar()->height() - 4); statusBar()->addWidget(widget); } // Start the build process. ProjectManager::engine().build(&buildProgress_); } catch (Core::Exception* e) { e->showMessage(); delete e; } } /** * Opens the given file for editing. * @param path The path of the requested file */ void MainWindow::openFile(const QString& path) { editCont_->gotoLocation(Core::Location(path)); } /** * Handles the "Project->New..." action. * Closes the current project, and displays the "New Project" dialogue. */ void MainWindow::newProject() { // If an active project exists, it needs to be closed first. if (ProjectManager::hasProject()) { QString msg = tr("The active project needs to be closed.\n" "Would you like to close it now?"); int result = QMessageBox::question(this, tr("Close Project"), msg, QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No || !closeProject()) return; } // Show the "New Project" dialogue. ProjectDialog dlg(this); dlg.setParamsForProject(NULL); if (dlg.exec() == QDialog::Rejected) return; // Get the new parameters from the dialogue. Core::ProjectBase::Params params; dlg.getParams(params); try { // Create a project. Cscope::ManagedProject proj; proj.create(params); // Load the new project. ProjectManager::load(params.projPath_); } catch (Core::Exception* e) { e->showMessage(); delete e; return; } } /** * Handles the "Project->Open" action. * Displays the "Open Project" dialogue. */ void MainWindow::openProject() { // If an active project exists, it needs to be closed first. if (ProjectManager::hasProject()) { QString msg = tr("The active project needs to be closed.\n" "Would you like to close it now?"); int result = QMessageBox::question(this, tr("Close Project"), msg, QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No || !closeProject()) return; } // Show the "Open Project" dialogue. OpenProjectDialog dlg(this); switch (dlg.exec()) { case OpenProjectDialog::Open: try { ProjectManager::load(dlg.path()); } catch (Core::Exception* e) { e->showMessage(); delete e; } break; case OpenProjectDialog::New: newProject(); break; default: ; } } /** * Handles the "Project->Close" action. * Closes all editor windows, and saves the session (if it is part of a * project). * @return true if the session was closed, false if the user aborts the * operation (e.g., chooses to cancel when prompted to save a modified * editor) */ bool MainWindow::closeProject() { // Check all editors for unsaved changes. if (!editCont_->canClose()) return false; if (ProjectManager::hasProject()) { // Store session information. Session session(ProjectManager::project()->path()); editCont_->saveSession(session); queryDock_->saveSession(session); queryDock_->closeAll(); session.save(); } // Close open editor windows. editCont_->closeAll(); // Reset histories. queryDlg_->clear(); editCont_->clearHistory(); // Close the project. ProjectManager::close(); return true; } /** * Handles the "Project->Files..." action. * Shows the "Project Files" dialogue. */ void MainWindow::projectFiles() { ProjectFilesDialog dlg(this); dlg.exec(); } /** * Handles the "Project->Properties..." action. * Shows the "Project Properties" dialogue. */ void MainWindow::projectProperties() { // Get the active project. const Cscope::ManagedProject* project = dynamic_cast (ProjectManager::project()); if (project == NULL) return; // Create the project properties dialogue. ProjectDialog dlg(this); dlg.setParamsForProject(project); if (dlg.exec() == QDialog::Rejected) return; // Get the new parameters from the dialogue. Core::ProjectBase::Params params; dlg.getParams(params); bool rebuild = false; try { // Update project properties. ProjectManager::updateConfig(params); // Check if the project needs to be rebuilt. if (ProjectManager::engine().status() == Core::Engine::Rebuild) rebuild = true; } catch (Core::Exception* e) { e->showMessage(); delete e; } // Prompt the user for rebuilding the project. if (rebuild) { QString msg = tr("This project needs to be rebuilt.\nWould you like to" " build it now?"); if (QMessageBox::question(this, tr("Rebuild Prject"), msg, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { buildProject(); } } } /** * Handles the "Settings->Configure Engines" action. */ void MainWindow::configEngines() { ConfigEnginesDialog dlg(this); dlg.exec(); } /** * Called before the main window closes. * @param event Information on the closing event */ void MainWindow::closeEvent(QCloseEvent* event) { if (!closeProject()) { event->ignore(); return; } // Save main-window geometry. writeSettings(); // Close the main window and terminate the application. event->accept(); } /** * Stores configuration in the settings file. */ void MainWindow::writeSettings() { // Store main window position and size. Settings& settings = Application::settings(); settings.beginGroup("MainWindow"); settings.setValue("size", size()); settings.setValue("pos", pos()); settings.setValue("state", saveState()); settings.endGroup(); } /** * Loads configuration from the settings file. */ void MainWindow::readSettings() { // Restore main window position and size. Settings& settings = Application::settings(); settings.beginGroup("MainWindow"); resize(settings.value("size", QSize(1000, 600)).toSize()); move(settings.value("pos", QPoint(200, 200)).toPoint()); restoreState(settings.value("state").toByteArray()); settings.endGroup(); } /** * Changes the window title to reflect the availability of a project. * @param hasProject true if a project is currently open, false otherwise */ void MainWindow::setWindowTitle(bool hasProject) { QString title = qApp->applicationName(); if (hasProject) title += " - " + ProjectManager::project()->name(); QMainWindow::setWindowTitle(title); } /** * Performs actions following the opening or closing of a project. * This slot is connected to the hasProject() signal emitted by the project * manager. * @param opened true if a project was opened, false if a project was closed */ void MainWindow::projectOpenedClosed(bool opened) { // Adjust the window title. setWindowTitle(opened); // Nothing else to to if a project was closed. if (!opened) return; // Restore the session. Session session(ProjectManager::project()->path()); session.load(); editCont_->loadSession(session); queryDock_->loadSession(session); try { // Show the project files dialogue if files need to be added to the // project. if (ProjectManager::codebase().needFiles()) projectFiles(); } catch (Core::Exception* e) { e->showMessage(); delete e; } } } // namespace App } // namespace KScope kscope-1.9.4/app/images/0000755000175000001440000000000011156714402014216 5ustar elahavuserskscope-1.9.4/app/images/show.png0000644000175000001440000000121211156714353015705 0ustar elahavusers‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÖ 5âwßš5tEXtComment(c) 2004 Jakub Steiner Created with The GIMPÙ‹oÖIDAT8Ë“;h“QÇÿ›5iÓ%Hñq‚ ”*v*_PÅÉÇàÐÁ*ÕÅAppHùšà¨`ÁAPíà³VQtPq -Š%-EjMSMLûuø’ؼràÀ…sÏïþϹçȉEoý4g œXÔmÖœXÔµ%ÔîþÛè'ýHpé¹ø¨"þ.qS­ÉýK$ÄÓø~ŒQM ¦:yCÀÏ…ëo¼—ePÑO9/hYk±>ÕH0æô²±=@¸£•{¯g<wždÇÖvBÁãñƒøV))÷`hh?y‹­öÜù†'æÏ¸£u|×0äwo%ÍUý±/»¶…µÏ2}™ 1„î9™AŽ€cƒ™pHئ堛 î:¬¨|ÿ‘Àãó¾:°Ä_$<ò›·0éA¾¾*DaÁ@´V;žL-µ¤>eñ¯÷¶ù¯>eés{±]…R W JR¿›3¦(ñÉ’%ôϘqcïL¿;þÉ;J\wˆ´ëo¿_/1S‰RJžZ[.J)ÙsøcQªý\(šK!].Eå̧WäŸïÕK‰¿Htã¤DcÇ$a׊e”ÇçË©÷çËžZ‘=µ"«ÑGD¤s7•Râ¤ætKIKÌ–æˆ)MÁ˜|Rj·íIØuUɬoÊ«¯ŒH‹˜óý¢eJ±#‡›Ýqxp8.8®`;–å°gw1K–Tà¸ݲ Á“ÊÆQaêïŠ\fMÉnæLÍ£ðþnž6 FEuM»¹Gkضõ®<ŽWËA¹¶!n^¦©ùã6ð˜i¢.13Á©sj_{O»¥¨¨®áÑYÃÛ¬©¨®á;ßA4|Ç”r°•Ž0¹Ò$nu ëñ׎h·•„ P jÏ=ÃÀÂÙ8®…ã˜X “H¼ãàp“JØYÓ€{§e3èÎ\¶ø‹éŽåè膑03«^<:‘®Û¹­]Pˆòм\vï|š1£¾HÉæç1Ì(ºa ß>sÌÊv¶º,@€å+±sûòûáÙgJi ^cãË/¡›zFøo~TÑ¡½. `Þ‚<¶––Ò#·ˆ^y3ðzû³qÍÏø°¦…ͻʉF;øïŸÞ‹×Û1ªKZáÝ»Ñ-çD9ÄÍK|Tw–Ÿ<9ƒP‹ÅoËþÂù@ ß°|^¯¯ç6´¢¹)xnÎ ²³ûa»aZô³|rá Y9ˆ–ŃÓGs1dàßÿ¶8Aéªøÿ|ǃ׫uh¿Ó]°~Û!‚g±µ´”n9ø²{$ ä|ðSL3ek¸Z/vVž`ÊÃ|eÔD`ý¶ƒé"6þž‚ÛÐ ÏÊî‹×ÓD"BLÑtµ)p¡h”Òòc¬ZTÅÔ±…(•¬-«ø5*ªk˜82%·áV·{³zãÁ‡‘7£\7ß?Â~ÿ¿W!"hš† ¤â 9×e/–<Þ<”ë·ãVœP,Ò¾tèn¨ÆÒ¦ƒ¥[$ '=Nè –½ñ½7MÂ}oîÆ¶ âf„kz¤Cøòâ”RˆD¢¢R%ˆ+étÉÅSr?*ÂÁû=rf› × _9~S玦OAOuWxsóÛ(W’ÝN=•BA£ !X¸èNTþо}§°pÙw‰DáK#'¶¯š°‰~ƒ{Ó;?7^:F^Ÿ\Ä\W¡R‡Uå$»ëdör»L~°‡¯ZG¿~×™;{2Øq‚Êê#®6SZ~„5ÓËÐ4 ŸÏƒ7ËCa0¡` ãšÅð ƒ7shî^»rå$Ÿ†`ö‚>²c“¯§7áhÍM\¸tžu/¿Ã®"a¸¼ú­r,Ó¡rËq–ƒm:¼þüQlÓÆÒ\W¥p¤'ÄI%§« “€Ü!)Måk+€\®F¹ÒæÂÅ:~|Ùß° ;yép“Y®$ùUɱি8åzEòË• Ž næð½¾c§Î†øB÷¡„¯55âixmU¶–£€Ö;ém¥>s—PJpU²ø¸J¡$µN$S€ï¾É‹øéº§=ú8ýû§áKç—áåPféÿ§¦5‡H8rš‡ûyhúH*×Sw¨Q&|^Pùwz°líX©m,“wO¯•…+ÇIþýƒ¥£ëÚçÕÿÀ§}!·X¿ˆIEND®B`‚kscope-1.9.4/app/images/close.png0000644000175000001440000000044511156714353016041 0ustar elahavusers‰PNG  IHDR‘h6tEXtSoftwareAdobe ImageReadyqÉe<ÇIDATxÚb¼Í Í@ `b  hàK‹fää@r‚(:€N‚ ÷æüÿÿÿëöýwØ "w8•\  P ® ªáeZÙ€è"ˆj*@Ñ7 ® TQÉ% s%×Íáòp@óå·ž¥üÿþÝÓ@! PjŒ`ýûK@¢ 2!‡ äÆùhNr‚(aMª§q+§2šèÁŠq0ðF#r⦂ϋ×"‡ Ðõ¼±ÁŸf-EˆÐ<µa6â•XIEND®B`‚kscope-1.9.4/app/addfilesdialog.cpp0000644000175000001440000001600111156714354016414 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include #include #include #include "addfilesdialog.h" #include "projectmanager.h" namespace KScope { namespace App { struct FileFilter { QString filter_; bool include_; }; typedef QList FileFilterList; /** * A filter proxy model for QFileDialog. * The model is used to to display filtered items in the QFileDialog used for * selecting files to add to the project. * @note There is a bug in Qt versions 4.4.3 and below, which causes the * file dialogue to crash when using a proxy. This bug is supposed to be * fixed in 4.4.4. * @author Elad Lahav */ class FileFilterProxy : public QSortFilterProxyModel { public: FileFilterProxy(const QString& filter, QObject* parent = NULL) : QSortFilterProxyModel(parent), filter_(filter) {} protected: bool filterAcceptsRow (int row, const QModelIndex& parent) const { // Get the inspected index from the source model. QModelIndex index = sourceModel()->index(row, 0, parent); if (!index.isValid()) return false; // We need to distinguish directories from files somehow. We do this by // appending a trailing '/' to the file name. // TODO: Is there a safer way to check for directories than querying // about index children? QString name = sourceModel()->data(index).toString(); if (sourceModel()->hasChildren(index)) name += "/"; // Query the filter. return filter_.match(name, true); } private: Core::FileFilter filter_; }; /** * Class constructor. * @param parent Parent widget */ AddFilesDialog::AddFilesDialog(QWidget* parent) : QDialog(parent), Ui::AddFilesDialog() { setupUi(this); } /** * Class destructor. */ AddFilesDialog::~AddFilesDialog() { } /** * Generates a list of all the files selected for addition. * @param list The list object to fill */ void AddFilesDialog::fileList(QStringList& list) const { QListWidgetItem* item; int i = 0; while ((item = fileList_->item(i++))) list.append(item->text()); } /** * Prompts the user for files to add. */ void AddFilesDialog::addFiles() { QStringList list; if (getFiles(QFileDialog::ExistingFiles, list)) fileList_->addItems(list); } /** * Prompts the user for a directory to add. * These include all files under the selected directory which match the current * filter. */ void AddFilesDialog::addDir() { addTree(false); } /** * Prompts the user for a directory to add. * These include all files under the selected directory, as well as any of its * sub-directories, which match the current filter. */ void AddFilesDialog::addTree() { addTree(true); } /** * Prompts the user for a text file which contains a file filter. * The first line in the selected file is set as the current filter. */ void AddFilesDialog::loadFilter() { // Prompt for a file. QString path = QFileDialog::getOpenFileName(this, tr("Load Filter")); if (path.isEmpty()) return; // Open the file. QFile file(path); if (!file.open(QIODevice::ReadOnly)) { QString msg = tr("Failed to open '%1'").arg(path); QMessageBox::critical(this, tr("File Error"), msg); return; } // Set the first line as the current filter. QTextStream str(&file); filterEdit_->setText(str.readLine()); } /** * Prompts the user for a file, into which the current filter is saved. */ void AddFilesDialog::saveFilter() { // Prompt for a file. QString path = QFileDialog::getSaveFileName(this, tr("Save Filter")); if (path.isEmpty()) return; // Open the file. QFile file(path); if (!file.open(QIODevice::WriteOnly)) { QString msg = tr("Failed to open '%1'").arg(path); QMessageBox::critical(this, tr("File Error"), msg); return; } // Store the current filter. QTextStream str(&file); str << Core::FileFilter(filterEdit_->text()).toString(); } /** * Deletes the selected items from the file list. */ void AddFilesDialog::deleteSelectedFiles() { // Get the currently selected items. QList selectedItems = fileList_->selectedItems(); // Delete the selected items. QList::Iterator itr; for (itr = selectedItems.begin(); itr != selectedItems.end(); ++itr) delete *itr; } /** * Creates a file dialog. * This method is used by the various add() functions. * @param mode The type of file dialogue to display * @param list A list object to fill with selected file/directory names * @return true if successful, false if the user cancelled selection */ bool AddFilesDialog::getFiles(QFileDialog::FileMode mode, QStringList& list) { QFileDialog dlg(this); dlg.setDirectory(ProjectManager::project()->rootPath()); dlg.setFileMode(mode); // TODO: Re-enable when the proxy bug in QFileDialog gets fixed. #if 0 FileFilterProxy* proxy = new FileFilterProxy(filterEdit_->text()); dlg.setProxyModel(proxy); #endif if (dlg.exec() == QDialog::Rejected) return false; list = dlg.selectedFiles(); return true; } /** * Service method for addDir() and addTree(). * Prompts the user for a directory, and then adds all files under this * directory that match the current filter. * @param recursive true to descend into sub-directories, false otherwise */ void AddFilesDialog::addTree(bool recursive) { // Prompt the user for a directory. QStringList list; if (!getFiles(QFileDialog::DirectoryOnly, list)) return; // Create the scanner object. Core::FileScanner scanner(this); scanner.setProgressMessage(tr("Found %2 of %1 files")); // Create a modal progress dialogue. // This will be used to display progress information, as well as allow the // user to cancel scanning. QProgressDialog dlg(tr("Scanning..."), tr("Cancel"), 0, 0, this); dlg.setModal(true); connect(&dlg, SIGNAL(canceled()), &scanner, SLOT(stop())); connect(&scanner, SIGNAL(progress(const QString&)), &dlg, SLOT(setLabelText(const QString&))); dlg.show(); QString filter = filterEdit_->text(); // Scan for files. if (scanner.scan(list.first(), Core::FileFilter(filter), recursive)) fileList_->addItems(scanner.matchedFiles()); } } } kscope-1.9.4/app/configenginesdialog.cpp0000644000175000001440000000537411156714354017472 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "application.h" #include "configenginesdialog.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ ConfigEnginesDialog::ConfigEnginesDialog(QWidget* parent) : QDialog(parent), Ui::ConfigEnginesDialog() { setupUi(this); // TODO: We'd like a list of engines that can be iterated over in compile // time to generate multi-engine code. typedef Core::EngineConfig Config; QWidget* widget = Config::createConfigWidget(this); QString title; if (widget) { title = widget->windowTitle(); } else { widget = new QLabel(tr("Configuration not available"), this); title = Config::name(); } tabWidget_->addTab(widget, title); } /** * Class destructor. */ ConfigEnginesDialog::~ConfigEnginesDialog() { } /** * Called when the user clicks the "OK" button. * Applies the configuration to the engines, and exits the dialogue. */ void ConfigEnginesDialog::accept() { // TODO: We'd like a list of engines that can be iterated over in compile // time to generate multi-engine code. typedef Core::EngineConfig Config; // Apply configuration to the engine. Config::configFromWidget(tabWidget_->widget(0)); // Get the new set of parameters. Core::KeyValuePairs params; Config::getConfig(params); Settings& settings = Application::settings(); // Prefix group with "Engine_" so that engines do not overrun application // groups by accident. settings.beginGroup(QString("Engine_") + Config::name()); // Write the new configuration parameters. Core::KeyValuePairs::Iterator itr; for (itr = params.begin(); itr != params.end(); ++itr) settings.setValue(itr.key(), itr.value()); settings.endGroup(); QDialog::accept(); } } // namespace App } // namespace Kscope kscope-1.9.4/app/editorcontainer.cpp0000644000175000001440000004305111156714354016657 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include "application.h" #include "editorcontainer.h" #include "queryresultdialog.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ EditorContainer::EditorContainer(QMainWindow* parent) : QMdiArea(parent), currentWindow_(NULL), newFileIndex_(1), windowActivationBlocked_(false) { // Load editor configuration settings. Settings& settings = Application::settings(); settings.beginGroup("Editor"); config_.load(settings); settings.endGroup(); // Notify when an active editor is available. connect(this, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(windowActivated(QMdiSubWindow*))); // Display the edit mode for the current editor the status bar. editModeLabel_ = new QLabel(tr("N/A"), this); parent->statusBar()->addPermanentWidget(editModeLabel_); // Display the current cursor position in the status bar. cursorPositionLabel_ = new QLabel(tr("Line: N/A Column: N/A"), this); parent->statusBar()->addPermanentWidget(cursorPositionLabel_); } /** * Class destructor. */ EditorContainer::~EditorContainer() { } void EditorContainer::initActions(QMenu* menu) { actions_.setupMenu(menu); } /** * Fills the "Window" menu with a list of all open sub-window titles. * @param wndMenu The menu to populate */ void EditorContainer::populateWindowMenu(QMenu* wndMenu) const { // Add an entry for each open sub-window. QMap::ConstIterator itr; for (itr = fileMap_.begin(); itr != fileMap_.end(); ++itr) wndMenu->addAction(itr.key()); // Activate a sub-window when its menu entry is selected. connect(wndMenu, SIGNAL(triggered(QAction*)), this, SLOT(handleWindowAction(QAction*))); } /** * Checks for any unsaved-changes in the currently open editors. * @return true if the application can terminate, false if the user cancels * the operation due to unsaved changes */ bool EditorContainer::canClose() { // TODO: Saving a file may take too long (e.g., for NFS-mounted files). // In this case, the application should not terminate until the file has // been saved. The current behaviour may lead to data loss! // Iterate over all editor windows. foreach (QMdiSubWindow* window, fileMap_) { Editor::Editor* editor = editorFromWindow(window); if (!editor->canClose()) return false; } return true; } /** * Stores the locations of all editors in a session object. * @param session The session object to use */ void EditorContainer::saveSession(Session& session) { Core::LocationList locList; // Create a list of locations for the open editors. foreach (QMdiSubWindow* window, fileMap_) { Editor::Editor* editor = editorFromWindow(window); Core::Location loc; editor->getCurrentLocation(loc); locList.append(loc); } session.setEditorList(locList); // Store the path of the currently active editor. if (currentEditor()) session.setActiveEditor(currentEditor()->path()); // Store the state of the active window. QMdiSubWindow* window = currentSubWindow(); session.setMaxActiveEditor(window ? window->isMaximized() : false); } /** * Opens editors based on the locations stored in a session object. * @param session The session object to use */ void EditorContainer::loadSession(Session& session) { const Core::LocationList& locList = session.editorList(); Core::LocationList::ConstIterator itr; // Do not handle changes to the active editor while loading. blockWindowActivation(true); // Open an editor for each location. for (itr = locList.begin(); itr != locList.end(); ++itr) (void)gotoLocationInternal(*itr); // Activate the previously-active editor. // We have to call windowActivated() explicitly, in the case the active // window is the last one to be loaded. In that case, the signal will not // be emitted. QString activeEditor = session.activeEditor(); if (!activeEditor.isEmpty()) (void)findEditor(activeEditor); // Re-enable handling of changes to active windows. blockWindowActivation(false); // Maximise the active window, if required. if (session.maxActiveEditor()) currentSubWindow()->showMaximized(); } /** * Deletes all location items in the history list. */ void EditorContainer::clearHistory() { history_.clear(); } /** * Creates an editor window with an empty, unnamed file. */ void EditorContainer::newFile() { (void)createEditor(QString()); } /** * Prompts the user for a file name, and creates an editor window for editing * the selected file. */ void EditorContainer::openFile() { QString path = QFileDialog::getOpenFileName(0, tr("Open File")); if (!path.isEmpty()) (void)gotoLocationInternal(Core::Location(path)); } /** * Displays the editor configuration dialogue. * Any changes to the configuration are then applied to all open editor windows. */ void EditorContainer::configEditor() { // Show the "Configure Editor" dialogue. Editor::ConfigDialog dlg(config_, this); if (dlg.exec() == QDialog::Rejected) return; // Get the configuration parameters from the dialogue. dlg.getConfig(config_); // Store the editor configuration. Settings& settings = Application::settings(); settings.beginGroup("Editor"); config_.store(settings); settings.endGroup(); // Apply new settings to all open editors. foreach (QMdiSubWindow* window, fileMap_) config_.apply(editorFromWindow(window)); } /** * Sets the focus to a line in an editor window matching the given location. * @param loc The location to go to */ void EditorContainer::gotoLocation(const Core::Location& loc) { // Get the current location. Core::Location curLoc; bool addCurrent = false; if (currentEditor()) { currentEditor()->getCurrentLocation(curLoc); addCurrent = true; } // Go to the new location. if (!gotoLocationInternal(loc)) return; // Add both the previous and the new locations to the history list. if (addCurrent) history_.add(curLoc); history_.add(loc); } /** * Sets the focus to a line in an editor window matching the next location in * the history list. */ void EditorContainer::gotoNextLocation() { Core::Location loc; if (history_.next(loc)) (void)gotoLocationInternal(loc); } /** * Sets the focus to a line in an editor window matching the previous location * in the history list. */ void EditorContainer::gotoPrevLocation() { Core::Location loc; if (history_.prev(loc)) (void)gotoLocationInternal(loc); } /** * Shows a list of tags defined in the file of currently-active editor. */ void EditorContainer::showLocalTags() { if (!currentEditor()) return; // Create a query view dialogue. QueryResultDialog* dlg = new QueryResultDialog(this); dlg->setModal(true); // Go to selected locations. Core::QueryView* view = dlg->view(); connect(view, SIGNAL(locationRequested(const Core::Location&)), this, SLOT(gotoLocation(const Core::Location&))); dlg->setWindowTitle(tr("Local Tags")); dlg->show(); try { // Run the query. Core::LocationModel* model = view->locationModel(); model->setRootPath(ProjectManager::project()->rootPath()); model->setColumns(ProjectManager::engine() .queryFields(Core::Query::LocalTags)); ProjectManager::engine().query(view, Core::Query(Core::Query::LocalTags, currentEditor()->path())); } catch (Core::Exception* e) { e->showMessage(); delete e; } } /** * Shows a dialogue with the list of recently visited locations. */ void EditorContainer::browseHistory() { // Construct the dialogue. QueryResultDialog dlg(this); dlg.setWindowTitle(tr("Location History")); // Add location history entries to the model. Core::QueryView* view = dlg.view(); Core::LocationModel* model = view->locationModel(); model->add(history_.list(), QModelIndex()); // Setup the model's displayed columns. QList columns; columns << Core::Location::File << Core::Location::Line << Core::Location::Text; model->setColumns(columns); try { // Set the root path. model->setRootPath(ProjectManager::project()->rootPath()); } catch (Core::Exception* e) { e->showMessage(); delete e; } view->resizeColumns(); // Go to selected locations. connect(view, SIGNAL(locationRequested(const Core::Location&)), this, SLOT(gotoLocation(const Core::Location&))); // Display the dialogue. dlg.exec(); } /** * Changes the current editor and cursor position to the given location. * Creates a new editor window if one is not currently open for the location's * file. * @param loc The location to go to * @return true if successful, false otherwise */ bool EditorContainer::gotoLocationInternal(const Core::Location& loc) { // Get an editor for the given file. // If one does not exists, create a new one. Editor::Editor* editor = findEditor(loc.file_); if (editor == NULL) { editor = createEditor(loc.file_); if (editor == NULL) return false; } // Set the cursor position for the editor. editor->moveCursor(loc.line_, loc.column_); return true; } /** * Finds an editor sub-window matching the file. * @param path The path of the file to edit * @return The found editor if successful, NULL otherwise */ Editor::Editor* EditorContainer::findEditor(const QString& path) { // Try to find an existing editor window, based on the path. QMap::Iterator itr = fileMap_.find(path); if (itr == fileMap_.end()) return NULL; // Get the editor widget for the window. QMdiSubWindow* window = *itr; Editor::Editor* editor = editorFromWindow(window); // Activate the window. if (window != currentSubWindow()) setActiveSubWindow(window); else editor->setFocus(); return editor; } /** * Creates a new editor sub-window for the given file. * @param path The path to the file to edit * @return The editor widget if successful, false otherwise */ Editor::Editor* EditorContainer::createEditor(const QString& path) { Editor::Editor* editor = new Editor::Editor(this); // Open the given file in the editor. if (!path.isEmpty()) { if (!editor->load(path, config_.lexer(path))) { delete editor; return NULL; } } else { // No path supplied, treat as a new file. editor->setNewFileIndex(newFileIndex_++); } // Set configuration parameters. config_.apply(editor); // Handle editor closing/name changes. connect(editor, SIGNAL(closed(const QString&)), this, SLOT(removeEditor(const QString&))); connect(editor, SIGNAL(titleChanged(const QString&, const QString&)), this, SLOT(remapEditor(const QString&, const QString&))); // Show editor messages in the status bar. connect(editor, SIGNAL(message(const QString&, int)), static_cast(parent())->statusBar(), SLOT(showMessage(const QString&, int))); // Create a new sub window for the editor. QMdiSubWindow* window = addSubWindow(editor); window->setAttribute(Qt::WA_DeleteOnClose); window->setWindowTitle(editor->title()); window->show(); fileMap_[editor->title()] = window; return editor; } /** * Enables/disables handling of changes to the active editor in * windowActivated(). * This is useful when doing mass-update operations, such as loading a session * or closing all files, to prevent unnecessary actions during the operation. * When activation is re-enabled, windowActivated() is called directly for the * currently active sub-window. * @param block true to disable handling, false to enable */ void EditorContainer::blockWindowActivation(bool block) { if (block) { windowActivationBlocked_ = true; } else { windowActivationBlocked_ = false; windowActivated(currentSubWindow()); } } /** * Closes all editor windows. */ void EditorContainer::closeAll() { // Prompt the user for unsaved changes. if (!canClose()) return; // Do not handle changes to the active editor while closing. blockWindowActivation(true); // Delete all editor windows. foreach (QMdiSubWindow* window, fileMap_) delete window; fileMap_.clear(); // No current window. currentWindow_ = NULL; showCursorPosition(0, 0); showEditMode(Editor::ViScintilla::Disabled); emit hasActiveEditor(false); // Re-enable handling of changes to active windows. blockWindowActivation(false); } /** * Common handler for the file names in the "Window" menu. * Activates the window corresponding to the chosen file. * @param action The triggered action */ void EditorContainer::handleWindowAction(QAction* action) { (void)gotoLocationInternal(Core::Location(action->text())); } /** * Handles changes to the active editor window. * When an editor becomes active, it needs to get the keyboard focus. Also, * the container forwards certain signals to the active editor, which need to * be connected. * Note that this method is also called when the MDI area gains or loses focus. * If the latter happens, the active sub window becomes NULL, even though the * current sub window stays the same. This method is only concerned with changes * to the current sub window. * @param window The new active editor */ void EditorContainer::windowActivated(QMdiSubWindow* window) { // Do nothing if activation signals are blocked. if (windowActivationBlocked_) return; // Do nothing if the active window is not the current one (i.e., a NULL // active window due to the MDI area losing focus). if (window != currentSubWindow()) return; // Do nothing if the new current window is the same as the old one. if (window == currentWindow_) return; // Stop forwarding signals to the active editor. if (currentWindow_) disconnect(editorFromWindow(currentWindow_)); // Remember the current window. currentWindow_ = window; // Update the active editor. Editor::Editor* editor = currentEditor(); // Route editor actions to the active editor. actions_.setEditor(editor); if (!editor) { qDebug() << "No current editor"; showCursorPosition(-1, -1); showEditMode(Editor::ViScintilla::Disabled); emit hasActiveEditor(false); return; } qDebug() << "Current editor" << (editor ? editor->path() : ""); // Acquire keyboard focus. editor->setFocus(); // Show information in the status bar. connect(editor, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(showCursorPosition(int, int))); connect(editor, SIGNAL(editModeChanged(Editor::ViScintilla::EditMode)), this, SLOT(showEditMode(Editor::ViScintilla::EditMode))); // Update the current cursor position. // TODO: We have to update here, in case windowActivated() was called due // to an explicit user action. However, if called through // gotoLocationInternal(), the cursor position will change immediately after // returning. A better mechanism for updating the cursor position is // required. int line, column; editor->getCursorPosition(&line, &column); showCursorPosition(line, column); showEditMode(editor->editMode()); emit hasActiveEditor(true); } /** * Removes an editor from the file map when its window is closed. * @param title The unique title of the editor being closed */ void EditorContainer::removeEditor(const QString& title) { fileMap_.remove(title); qDebug() << title << "removed"; } /** * Changes the map key for an editor window. * This slot is called when an editor changes its title (e.g., following a * "Save As" operation). * @param oldTitle The previous title of the editor * @param newTitle The new title of the editor */ void EditorContainer::remapEditor(const QString& oldTitle, const QString& newTitle) { QMap::Iterator itr = fileMap_.find(oldTitle); if (itr != fileMap_.end()) { QMdiSubWindow* window = *itr; fileMap_.remove(oldTitle); fileMap_[newTitle] = window; } } /** * Updates the current line and column numbers displayed in the status bar. * @param line The line number * @param column The column number */ void EditorContainer::showCursorPosition(int line, int column) { QString text; if (line >= 0) text = QString(tr("Line: %1 ")).arg(line + 1); else text = tr("Line: N/A "); if (column >= 0) text += QString(tr("Column: %1 ")).arg(column + 1); else text += tr("Column: N/A "); cursorPositionLabel_->setText(text); } /** * Displays the edit mode of the current editor in the status bar. * @param mode The mode to show */ void EditorContainer::showEditMode(Editor::ViScintilla::EditMode mode) { switch (mode) { case Editor::ViScintilla::InsertMode: editModeLabel_->setText(tr("INSERT")); break; case Editor::ViScintilla::NormalMode: editModeLabel_->setText(tr("VI:NORMAL")); break; case Editor::ViScintilla::VisualMode: editModeLabel_->setText(tr("VI:VISUAL")); break; case Editor::ViScintilla::Disabled: editModeLabel_->setText(tr("N/A")); break; } } } // namespace App } // namespace KScope kscope-1.9.4/app/queryresultdialog.cpp0000644000175000001440000000273111156714354017252 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "queryresultdialog.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ QueryResultDialog::QueryResultDialog(QWidget* parent) : QDialog(parent), Ui::QueryResultDialog() { setupUi(this); // Close the dialogue when a selection is made. connect(view_, SIGNAL(locationRequested(const Core::Location&)), this, SLOT(accept())); } /** * Class destructor. */ QueryResultDialog::~QueryResultDialog() { } } // namespace App } // namespace KScope kscope-1.9.4/app/locationhistory.h0000644000175000001440000000743311156714354016371 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_LOCATIONHISTORY_H__ #define __APP_LOCATIONHISTORY_H__ #include #include #include namespace KScope { namespace App { /** * Keeps track of visited locations in the source code. * @author Elad Lahav */ class LocationHistory { public: /** * Class constructor. */ LocationHistory() : pos_(-1) {} /** * Class destructor. */ ~LocationHistory() {} /** * @return The list of locations */ const Core::LocationList& list() const { return locList_; } /** * Adds a location descriptor to the list. * The location is added immediately after the current position. If this * is not the end of the list, all locations following the new one are * discarded. * @note If the new location is "close" to the current one, than it just * replaces it in the history list. This keeps the list from being * cluttered by close moves. The current definition of close is * being on the same file, within 5 lines of each other. * @param loc The descriptor to add */ void add(const Core::Location& loc) { qDebug() << "Add history" << loc.file_ << loc.line_; // Replace the current location if it is within 5 lines of new one. if (pos_ >= 0) { Core::Location curLoc = locList_.at(pos_); if ((curLoc.file_ == loc.file_) && (qAbs((int)curLoc.line_ - (int)loc.line_) < 5)) { locList_[pos_] = loc; return; } } // Remove any location descriptors after the current position. while (pos_ < (locList_.size() - 1)) locList_.removeLast(); // Add the new descriptor. locList_.append(loc); pos_++; } /** * Retrieves the next descriptor in the list, updating the current position. * @param loc A descriptor to fill * @return true if successful, false if already at the end of the list */ bool next(Core::Location& loc) { if (pos_ == (locList_.size() - 1)) return false; // Update the current position. ++pos_; // Get the new current descriptor. Q_ASSERT(pos_ >= 0 && pos_ < locList_.size()); loc = locList_.at(pos_); return true; } /** * Retrieves the previous descriptor in the list, updating the current * position. * @param loc A descriptor to fill * @return true if successful, false if already at the beginning of the list */ bool prev(Core::Location& loc) { if (pos_ <= 0) return false; // Update the current position. --pos_; // Get the new current descriptor. Q_ASSERT(pos_ >= 0 && pos_ < locList_.size()); loc = locList_.at(pos_); return true; } /** * Removes all items. */ void clear() { locList_.clear(); pos_ = -1; } private: /** * The history is kept as a list of locations. */ QList locList_; /** * The current position in the history. */ int pos_; }; } // namespace App } // namespace KScope #endif // __APP_LOCATIONHISTORY_H__ kscope-1.9.4/app/settings.h0000644000175000001440000000321511156714354014771 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_SETTINGS_H__ #define __APP_SETTINGS_H__ #include #include namespace KScope { namespace App { /** * Manages application-wide configuration. * @author Elad Lahav */ class Settings : public QSettings { public: Settings(); ~Settings(); void load(); void store(); struct RecentProject { QString path_; QString name_; }; void addRecentProject(const QString&, const QString&); void removeRecentProject(const QString&); const QLinkedList& recentProjects() const { return recentProjects_; } private: QLinkedList recentProjects_; }; } // namespace App } // namespace KScope #endif // __APP_SETTINGS_H__ kscope-1.9.4/app/settings.cpp0000644000175000001440000000526011156714354015326 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "settings.h" namespace KScope { namespace App { Settings::Settings() : QSettings() { } Settings::~Settings() { } void Settings::load() { beginGroup("RecentProjects"); int size = beginReadArray("Project"); for (int i = 0; i < size; i++) { setArrayIndex(i); RecentProject proj; proj.path_ = value("Path").toString(); proj.name_ = value("Name").toString(); recentProjects_.append(proj); } endArray(); endGroup(); } void Settings::store() { beginGroup("RecentProjects"); beginWriteArray("Project"); QLinkedList::iterator itr; int i; for (itr = recentProjects_.begin(), i = 0; itr != recentProjects_.end(); ++itr, i++) { setArrayIndex(i); setValue("Path", (*itr).path_); setValue("Name", (*itr).name_); } endArray(); endGroup(); } void Settings::addRecentProject(const QString& path, const QString& name) { // If this is already the most recent project, only need to make sure that // the project name is up-to-date. if (!recentProjects_.isEmpty() && recentProjects_.first().path_ == path) { recentProjects_.first().name_ = name; return; } // Remove the path from the current list. removeRecentProject(path); // Prepend the project to the list. RecentProject proj; proj.path_ = path; proj.name_ = name; recentProjects_.prepend(proj); // Truncate list if it contains more than 10 projects. while (recentProjects_.size() > 10) recentProjects_.removeLast(); } void Settings::removeRecentProject(const QString& path) { QLinkedList::iterator itr; for (itr = recentProjects_.begin(); itr != recentProjects_.end(); ++itr) { if ((*itr).path_ == path) itr = recentProjects_.erase(itr); } } } // namespace App } // namespace KScope kscope-1.9.4/app/openprojectdialog.cpp0000644000175000001440000001050511156714354017174 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "openprojectdialog.h" #include "application.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ OpenProjectDialog::OpenProjectDialog(QWidget* parent) : QDialog(parent), Ui::OpenProjectDialog() { setupUi(this); } /** * Class destructor. */ OpenProjectDialog::~OpenProjectDialog() { } /** * Shows the dialogue in modal mode. * @return See ExecResult */ OpenProjectDialog::ExecResult OpenProjectDialog::exec() { // Populate the "Recent Projects" list. bool first = true; foreach (Settings::RecentProject proj, Application::settings().recentProjects()) { QListWidgetItem* item = new QListWidgetItem(proj.name_, recentProjectsList_); item->setData(Qt::UserRole, proj.path_); // Select the first item. if (first) { item->setSelected(true); first = false; } } // Show the dialogue. if (QDialog::exec() == Rejected) return Cancel; return pathEdit_->text().isEmpty() ? New : Open; } /** * Called when the user clicks the "..." button next to the path edit widget. * Shows the standard "Select Directory" dialogue. * The directories available for selection are the visible ones, as well as * hidden directories called ".kscope". */ void OpenProjectDialog::browse() { // Set up the dialogue. QFileDialog dlg(this); dlg.setFileMode(QFileDialog::DirectoryOnly); dlg.setNameFilter("[^\\.]* .kscope"); dlg.setFilter(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); // Show the dialogue. if ((dlg.exec() == QDialog::Rejected) || dlg.selectedFiles().isEmpty()) return; // Get the selected path. QString path = dlg.selectedFiles().first(); if (!path.isEmpty()) pathEdit_->setText(path); } /** * Called when the user clicks the "New..." button. * Closes the dialogue, indicating that a new project was requested. */ void OpenProjectDialog::newProject() { pathEdit_->setText(""); accept(); } /** * Enables/disables the "Open" button, depending on whether the path widget * contains text. * @param path The text in the path edit widget */ void OpenProjectDialog::pathChanged(const QString& path) { openButton_->setDisabled(path.isEmpty()); } /** * Called when selection changes in the "Recent Projects" list. * If an item is selected, its path is set in the path edit widget. * The method also controls the "Remove" button, which is enabled if and only * is a project item is selected. */ void OpenProjectDialog::recentProjectSelected() { // Check if any item was selected. if (recentProjectsList_->selectedItems().isEmpty()) { removeProjectButton_->setEnabled(false); return; } // Extract the project's path from the item. QListWidgetItem* item = recentProjectsList_->selectedItems().first(); pathEdit_->setText(item->data(Qt::UserRole).toString()); removeProjectButton_->setEnabled(true); } /** * Called when the "Remove" button is clicked. * Removes the currently selected project from the list of recent projects. */ void OpenProjectDialog::removeProject() { // We can safely get the first item, since the "Remove" button is only // enabled when there is a non-empty selection list. QListWidgetItem* item = recentProjectsList_->selectedItems().first(); QString path = item->data(Qt::UserRole).toString(); Application::settings().removeRecentProject(path); delete item; } } // namespace App } // namespace KScope kscope-1.9.4/app/projectfilesdialog.ui0000644000175000001440000000716011156714354017173 0ustar elahavusers ProjectFilesDialog 0 0 498 479 Project Files true true true false true Qt::Horizontal &Add... &Remove... Qt::Horizontal 40 20 &OK &Cancel addButton_ clicked() ProjectFilesDialog addFiles() 64 457 22 475 removeButton_ clicked() ProjectFilesDialog removeFiles() 142 461 141 480 okButton_ clicked() ProjectFilesDialog accept() 358 464 360 479 cancelButton_ clicked() ProjectFilesDialog reject() 453 458 452 479 addFiles() removeFiles() kscope-1.9.4/app/queryresultdock.cpp0000644000175000001440000001017711156714354016736 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "queryresultdock.h" #include "projectmanager.h" #include "strings.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ QueryResultDock::QueryResultDock(QWidget* parent) : QDockWidget(tr("Query Results"), parent) { setObjectName("QueryResultDock"); setWidget(new StackWidget(this)); } /** * Class destructor. */ QueryResultDock::~QueryResultDock() { } /** * Runs a query and displays its results in a query view. * @param query The query to run */ void QueryResultDock::query(const Core::Query& query, bool tree) { QueryView* view; if (tree) { QString title = tr("Call Tree: ") + Strings::toString(query); view = addView(title, Core::QueryView::Tree); } else { view = addView(Strings::toString(query), Core::QueryView::List); } // Run the query. try { view->query(query); } catch (Core::Exception* e) { e->showMessage(); delete e; } } /** * Stores the open query views in a session object. * @param session The object to use for storing the views */ void QueryResultDock::saveSession(Session& session) { QList widgetList = tabWidget()->widgets(); foreach (QWidget* widget, widgetList) { QueryView* view = static_cast(widget); session.addQueryView(view); } } /** * Restores query views from a session object. * @param session The session object to use */ void QueryResultDock::loadSession(Session& session) { for (Session::QueryViewIterator itr = session.beginQueryIteration(); !itr.isAtEnd(); ++itr) { QueryView* view = addView(itr.title(), itr.type()); itr.load(view); view->resizeColumns(); } } /** * Selects the next location in the current view. */ void QueryResultDock::selectNextResult() { QueryView* view = static_cast(tabWidget()->currentWidget()); if (view != NULL) view->selectNext(); } /** * Selects the next location in the current view. */ void QueryResultDock::selectPrevResult() { QueryView* view = static_cast(tabWidget()->currentWidget()); if (view != NULL) view->selectPrev(); } /** * Closes all open query windows. */ void QueryResultDock::closeAll() { tabWidget()->removeAll(); } /** * Creates a new query view and adds it to the container widget. * @param title The title of the query view * @param type Whether to create a list or a tree view * @return The created widget */ QueryView* QueryResultDock::addView(const QString& title, Core::QueryView::Type type) { // Create a new query view. QueryView* view = new QueryView(this, type); view->setWindowTitle(title); connect(view, SIGNAL(locationRequested(const Core::Location&)), this, SIGNAL(locationRequested(const Core::Location&))); try { Core::LocationModel* model = view->locationModel(); model->setRootPath(ProjectManager::project()->rootPath()); } catch (Core::Exception* e) { delete e; } // TODO: Provide a configurable option to determine if a single result // should be selected automatically. if (type == Core::QueryView::List) view->setAutoSelectSingleResult(true); // Add to the tab widget. tabWidget()->addWidget(view); return view; } } // namespace App } // namespace KScope kscope-1.9.4/app/querydialog.h0000644000175000001440000000324011156714354015454 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_QUERYDIALOG_H__ #define __APP_QUERYDIALOG_H__ #include #include #include "ui_querydialog.h" namespace KScope { namespace App { /** * A dialogue that prompts for a query's type and pattern. * @author Elad Lahav */ class QueryDialog : public QDialog, private Ui::QueryDialog { Q_OBJECT public: typedef QList TypeList; QueryDialog(QWidget* parent = 0); ~QueryDialog(); int exec(Core::Query::Type, const TypeList& typeList = TypeList()); QString pattern(); void setPattern(const QString&); Core::Query::Type type(); void clear(); public slots: void accept(); }; } // namespace App } // namespace KScope #endif // __APP_QUERYDIALOG_H__ kscope-1.9.4/app/addfilesdialog.ui0000644000175000001440000002001411156714354016246 0ustar elahavusers AddFilesDialog 0 0 551 507 0 0 Add Files &Files... &Directory... &Tree... Qt::Horizontal 40 20 0 0 Filter *.c;*.h Qt::Horizontal 40 20 &Load... &Save As... 0 0 Files QAbstractItemView::ExtendedSelection De&lete &Clear Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() AddFilesDialog accept() 227 485 157 274 buttonBox rejected() AddFilesDialog reject() 295 491 286 274 filesButton_ clicked() AddFilesDialog addFiles() 66 27 89 8 dirButton_ clicked() AddFilesDialog addDir() 160 28 180 10 treeButton_ clicked() AddFilesDialog addTree() 240 29 304 18 clearFilesButton_ clicked() fileList_ clear() 495 236 440 251 loadFilterButton_ clicked() AddFilesDialog loadFilter() 430 130 538 17 saveFilterButton_ clicked() AddFilesDialog saveFilter() 506 127 544 114 deleteFileButton_ clicked() AddFilesDialog deleteSelectedFiles() 492 197 275 253 addFiles() addDir() addTree() loadFilter() saveFilter() deleteSelectedFiles() kscope-1.9.4/app/strings.h0000644000175000001440000000627511156714354014633 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_STRINGS_H__ #define __APP_STRINGS_H__ #include namespace KScope { namespace App { /** * Provides various conversions of types to strings. * @author Elad Lahav */ struct Strings { public: /** * Converts a query type to a string. * @param type The type to convert * @return A string describing the query type */ static QString toString(Core::Query::Type type) { switch (type) { case Core::Query::Invalid: return QObject::tr(""); case Core::Query::Text: return QObject::tr("Text Search"); case Core::Query::Definition: return QObject::tr("Definition"); case Core::Query::References: return QObject::tr("References"); case Core::Query::CalledFunctions: return QObject::tr("Called Functions"); case Core::Query::CallingFunctions: return QObject::tr("Calling Functions"); case Core::Query::FindFile: return QObject::tr("Search for File"); case Core::Query::IncludingFiles: return QObject::tr("Files #including"); case Core::Query::LocalTags: return QObject::tr("Symbols in This File"); } return QString(); } /** * Converts a query structure to a string. * @param query The query to convert * @return A string describing the query */ static QString toString(const Core::Query& query) { switch (query.type_) { case Core::Query::Invalid: return ""; case Core::Query::Text: return QObject::tr("Text search '%1'").arg(query.pattern_); case Core::Query::Definition: return QObject::tr("Definition of '%1'").arg(query.pattern_); case Core::Query::References: return QObject::tr("References to '%1'").arg(query.pattern_); case Core::Query::CalledFunctions: return QObject::tr("Functions called by '%1'").arg(query.pattern_); case Core::Query::CallingFunctions: return QObject::tr("Functions calling '%1'").arg(query.pattern_); case Core::Query::FindFile: return QObject::tr("Find file '%1'").arg(query.pattern_); case Core::Query::IncludingFiles: return QObject::tr("Files #including '%1'").arg(query.pattern_); case Core::Query::LocalTags: return QObject::tr("Symbols in '%1'").arg(query.pattern_); } return QString(); } }; } // namespace App } // namespace KScope #endif // __APP_STRINGS_H__ kscope-1.9.4/app/queryresultdialog.h0000644000175000001440000000273111156714354016717 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_QUERYRESULTDIALOG_H__ #define __APP_QUERYRESULTDIALOG_H__ #include #include "ui_queryresultdialog.h" namespace KScope { namespace App { /** * @author Elad Lahav */ class QueryResultDialog : public QDialog, private Ui::QueryResultDialog { Q_OBJECT public: QueryResultDialog(QWidget* parent = 0); ~QueryResultDialog(); Core::QueryView* view() { return view_; } }; } // namespace App } // namespace KScope #endif // __APP_QUERYRESULTDIALOG_H__ kscope-1.9.4/app/configenginesdialog.ui0000644000175000001440000000310311156714354017311 0ustar elahavusers ConfigEnginesDialog 0 0 512 409 Configure Engines 0 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() ConfigEnginesDialog accept() 248 254 157 274 buttonBox rejected() ConfigEnginesDialog reject() 316 260 286 274 kscope-1.9.4/app/stackwidget.h0000644000175000001440000000570311156714354015446 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __KSCOPE_STACKWIDGET_H__ #define __KSCOPE_STACKWIDGET_H__ #include #include #include #include "ui_stackpage.h" namespace KScope { namespace App { /** * A single page in a stack widget. * The page consists of a managed widget and a title bar. The title bar includes * a title for the page, and a "View" and "Close" buttons. */ class StackPage : public QWidget, public Ui::StackPage { Q_OBJECT public: StackPage(QWidget*, QWidget* parent = 0); ~StackPage(); /** * @return The managed widget */ QWidget* widget() { return widget_; } public slots: void showWidget(); void hideWidget(); signals: /** * Emitted when the widget is displayed. * @param page A pointer to this page */ void activated(StackPage* page); /** * Emitted when the page is closed. * @param page A pointer to this page */ void removed(StackPage* page); private: /** * The managed widget. */ QWidget* widget_; private slots: void remove(); }; /** * Manages multiple widgets in a vertical stack. * This widget is similar to QToolBox. Unlike QToolBox, however, each page has * a "Show" and "Close" buttons. * @author Elad Lahav */ class StackWidget : public QWidget { Q_OBJECT public: StackWidget(QWidget* parent = 0); ~StackWidget(); void addWidget(QWidget*); QList widgets() const; void removeAll(); /** * @return The widget of the active page, NULL if no page exists */ QWidget* currentWidget() { if (activePage_) return activePage_->widget(); return NULL; } private: /** * Vertical ayout for the pages. */ QVBoxLayout* layout_; /** * Keeps a list of pages. * This is used to determine the active page when the current one is closed. */ QLinkedList pageList_; /** * The currently active page. * This is the only page whose widget is visible. */ StackPage* activePage_; private slots: void setActivePage(StackPage*); void removePage(StackPage*); }; } } #endif // __KSCOPE_STACKWIDGET_H__ kscope-1.9.4/app/session.h0000644000175000001440000000622311156714354014616 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_SESSION_H__ #define __APP_SESSION_H__ #include #include #include "queryview.h" namespace KScope { namespace App { /** * Manages a KScope session. * Responsible for storing a session when a project is closed, and for restoring * it when the project is opened again. * @author Elad Lahav */ class Session { public: Session(const QString&); ~Session(); struct QueryViewIterator { void load(QueryView*); bool isAtEnd() { return listPos_ == queryNodeList_.size(); } QueryViewIterator& operator++() { for (++listPos_; listPos_ < queryNodeList_.size(); listPos_++) { elem_ = queryNodeList_.at(listPos_).toElement(); if (!elem_.isNull()) break; } title_ = elem_.attribute("name"); type_ = static_cast (elem_.attribute("type").toUInt()); return *this; } const QString& title() const { return title_; } Core::QueryView::Type type() const { return type_; } private: QDomNodeList queryNodeList_; int listPos_; QDomElement elem_; QString title_; Core::QueryView::Type type_; friend class Session; }; void load(); void save(); void addQueryView(const QueryView*); QueryViewIterator beginQueryIteration() const; #define PROPERTY(type, name, get, set) \ private: type name; \ public: type get() const { return name; } \ public: void set(type val) { name = val; } /** * A list of locations representing open editor windows. */ PROPERTY(Core::LocationList, editorList_, editorList, setEditorList); /** * The path of the file in the active editor. */ PROPERTY(QString, activeEditor_, activeEditor, setActiveEditor); /** * Whether the active editor window should be displayed maximised. */ PROPERTY(bool, maxActiveEditor_, maxActiveEditor, setMaxActiveEditor); private: /** * The path of the configuration directory holding session information. */ QString path_; /** * An XML document used to manage open query views. */ QDomDocument queryViewDoc_; inline QString configFile() { return path_ + "/session.conf"; } inline QString queryViewFile() { return path_ + "/queries.xml"; } }; } // namespace App } // namespace KScope #endif // __APP_SESSION_H__ kscope-1.9.4/app/application.cpp0000644000175000001440000001076711156714354016001 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "application.h" #include "mainwindow.h" #include "projectmanager.h" #include "version.h" namespace KScope { namespace App { /** * Class constructor. * @param argc The number of command-line arguments * @param argv Command-line argument list */ Application::Application(int& argc, char** argv) : QApplication(argc, argv) { QCoreApplication::setOrganizationName("elad_lahav@users.sourceforge.net"); QCoreApplication::setApplicationName("KScope"); QCoreApplication::setApplicationVersion(AppVersion::toString()); settings_ = new Settings(); } /** * Class destructor. */ Application::~Application() { delete settings_; } /** * Starts the application. * Note that this method only returns when the application terminates. * @return The return code of the application. */ int Application::run() { // Create the main window. // We can do it on the stack, as the method does not return as long as the // application is running. MainWindow mainWnd; mainWnd_ = &mainWnd; mainWnd_->show(); // Do application initialisation. // The reason for posting an event is to have a running application (event // loop) before starting the initialisation process. This way, the process // can take full advantage of the event mechanism. postEvent(this, new QEvent(static_cast(AppInitEvent))); // Run the event loop. int result = exec(); settings_->store(); return result; } /** * Displays application and version information. */ void Application::about() { QString msg; QTextStream str(&msg); str << "Source browsing, analysis and editing\n"; str << "Version " << applicationVersion() << "\n"; str << "Copyright (c) 2007-2009 by Elad Lahav\n"; str << "Distributed under the terms of the GNU Public License v2"; QMessageBox::about(mainWnd_, applicationName(), msg); } /** * Handles custom events. * @param event The event to handle. */ void Application::customEvent(QEvent* event) { if (event->type() == static_cast(AppInitEvent)) init(); } /** * Performs application initialisation, after the event loop was started. */ void Application::init() { // Load configuration. settings_->load(); setupEngines(); // Parse command-line arguments. // TODO: Need to think some more about the options. QString path; QStringList args = arguments(); while (!args.isEmpty()) { QString arg = args.takeFirst(); if (arg.startsWith("-")) { switch (arg.at(1).toLatin1()) { case 'f': path = args.takeFirst(); mainWnd_->openFile(path); return; case 'p': path = args.takeFirst(); ProjectManager::load(path); return; } } } // Prompt the user for opening a project. // TODO: Want more options on start-up (list of last projects, create new, // do nothing). mainWnd_->openProject(); } void Application::setupEngines() { // TODO: We'd like a list of engines that can be iterated over in compile // time to generate multi-engine code. typedef Core::EngineConfig Config; // Prefix group with "Engine_" so that engines do not overrun application // groups by accident. settings_->beginGroup(QString("Engine_") + Config::name()); // Add each value under the engine group to the map of configuration // parameters. Core::KeyValuePairs params; QStringList keys = settings_->allKeys(); QString key; foreach (key, keys) params[key] = settings_->value(key); settings_->endGroup(); // Apply configuration to the engine. Config::setConfig(params); } } // namespace App } // namespace KScope kscope-1.9.4/app/openprojectdialog.h0000644000175000001440000000423411156714354016643 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_OPENPROJECTDIALOG_H__ #define __APP_OPENPROJECTDIALOG_H__ #include #include "ui_openprojectdialog.h" namespace KScope { namespace App { /** * A dialogue that prompts the user for a project to open. * A project can be opened either by browsing for its path, or by choosing from * a list of recent projects. * It is also possible to select an option for creating a new project. * @author Elad Lahav */ class OpenProjectDialog : public QDialog, public Ui::OpenProjectDialog { Q_OBJECT public: OpenProjectDialog(QWidget* parent = 0); ~OpenProjectDialog(); /** * Possible return values for exec(). */ enum ExecResult { /** The user requested to open a project, using the provided path. */ Open, /** The user requested to create a new project. */ New, /** The "Cancel" button was clicked. */ Cancel }; ExecResult exec(); /** * @return The text currently selected in the path edit widget */ QString path() { return pathEdit_->text(); } private slots: void browse(); void newProject(); void pathChanged(const QString&); void recentProjectSelected(); void removeProject(); }; } // namespace App } // namespace KScope #endif // __APP_OPENPROJECTDIALOG_H__ kscope-1.9.4/app/queryresultdock.h0000644000175000001440000000367711156714354016412 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_QUERYRESULTDOCK_H__ #define __APP_QUERYRESULTDOCK_H__ #include #include "stackwidget.h" #include "queryview.h" #include "session.h" namespace KScope { namespace App { /** * A docked widget that holds query views. * @author Elad Lahav */ class QueryResultDock : public QDockWidget { Q_OBJECT public: QueryResultDock(QWidget* parent = 0); ~QueryResultDock(); void query(const Core::Query&, bool); void saveSession(Session&); void loadSession(Session&); public slots: void selectNextResult(); void selectPrevResult(); void closeAll(); signals: /** * Forwards a locationRequested() signal from any of the query views. * @param loc The requested location */ void locationRequested(const Core::Location& loc); private: inline StackWidget* tabWidget() { return static_cast(widget()); } QueryView* addView(const QString&, Core::QueryView::Type); }; } // namespace App } // namespace KScope #endif // __APP_QUERYRESULTDOCK_H__ kscope-1.9.4/app/projectdialog.cpp0000644000175000001440000000422211156714354016311 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "projectdialog.h" #include "application.h" namespace KScope { namespace App { /** * Class constructor. * @param parent Parent widget */ ProjectDialog::ProjectDialog(QWidget* parent) : QDialog(parent), Ui::ProjectDialog(), confWidget_(NULL) { setupUi(this); } /** * Class destructor. */ ProjectDialog::~ProjectDialog() { } void ProjectDialog::browseRootPath() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory")); if (!dir.isEmpty()) rootPathEdit_->setText(dir); } void ProjectDialog::browseProjectPath() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory")); if (!dir.isEmpty()) projectPathEdit_->setText(dir); } void ProjectDialog::updateProjectPath() { QString path; if (namedDirButton_->isChecked()) { path = projectPathEdit_->text(); if (!path.endsWith('/')) path += '/'; path += nameEdit_->text(); } else { path = rootPathEdit_->text(); if (!path.endsWith('/')) path += '/'; path += ".kscope"; } projectPathLabel_->setText(path); } } // namespace App } // namespace KScope kscope-1.9.4/app/main.cpp0000644000175000001440000000212411156714354014406 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "application.h" int main(int argc, char *argv[]) { KScope::App::Application app(argc, argv); return app.run(); } kscope-1.9.4/app/configenginesdialog.h0000644000175000001440000000305711156714354017133 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __APP_CONFIGENGINESDIALOG_H__ #define __APP_CONFIGENGINESDIALOG_H__ #include "ui_configenginesdialog.h" namespace KScope { namespace App { /** * A dialogue for configuring engines. * Each engine should create a configuration widget, which is placed inside a * tab container. * @author Elad Lahav */ class ConfigEnginesDialog : public QDialog, public Ui::ConfigEnginesDialog { Q_OBJECT public: ConfigEnginesDialog(QWidget* parent = NULL); ~ConfigEnginesDialog(); public slots: void accept(); }; } // namespace App } // namespace Kscope #endif // __APP_CONFIGENGINESDIALOG_H__ kscope-1.9.4/app/projectfilesdialog.h0000644000175000001440000000266211156714354017007 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __KSCOPE_PROJECTFILESDIALOG_H__ #define __KSCOPE_PROJECTFILESDIALOG_H__ #include #include "ui_projectfilesdialog.h" namespace KScope { namespace App { class ProjectFilesDialog : public QDialog, public Ui::ProjectFilesDialog { Q_OBJECT public: ProjectFilesDialog(QWidget* parent = NULL); ~ProjectFilesDialog(); public slots: void accept(); protected slots: void addFiles(); void removeFiles(); }; } } #endif // __KSCOPE_PROJECTFILESDIALOG_H__ kscope-1.9.4/core/0000755000175000001440000000000011156714402013121 5ustar elahavuserskscope-1.9.4/core/textfilterdialog.h0000644000175000001440000000320311156714354016650 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_TEXTFILTERDIALOG_H__ #define __CORE_TEXTFILTERDIALOG_H__ #include #include #include "ui_textfilterdialog.h" #include "globals.h" namespace KScope { namespace Core { /** * A dialogue for creating/modifying a text filter. * @author Elad Lahav */ class TextFilterDialog : public QDialog, public Ui::TextFilterDialog { Q_OBJECT public: TextFilterDialog(const QRegExp&, QWidget* parent = 0); ~TextFilterDialog(); void setFilterByList(const KeyValuePairs&); void setFilterByValue(const QVariant&); QRegExp filter() const; QVariant filterByValue() const; }; } // namespace Core } // namespace KScope #endif // __CORE_TEXTFILTERDIALOG_H__ kscope-1.9.4/core/filescanner.h0000644000175000001440000000561511156714354015600 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_FILESCANNER_H__ #define __CORE_FILESCANNER_H__ #include #include #include #include "filefilter.h" namespace KScope { namespace Core { /** * A FileFilter-based directory scanner. * Scans can be performed on the given directory only, or recursively. By * default, symbolic links are not followed, to simplify the scan. However, it * is possible to set an option for following symbolic links, which somewhat * degrades performance (as the scanner needs to keep track of visited * directories to avoid loops). * @author Elad Lahav */ class FileScanner : public QObject { Q_OBJECT public: FileScanner(QObject* parent = NULL); ~FileScanner(); bool scan(const QDir&, const FileFilter&, bool recursive = false); /** * Modifies the symbolic-link behaviour * @param follow true to follow symbolic links, false to not */ void setFollowSymLinks(bool follow) { followSymLinks_ = follow; } /** * Changes the type of progress signal emitted to be a formatted message. * The given string should include a '%1' marker to be replaced by the * number of scanned files, and a '%2' marker to be replaced by the * number of files matching the filter. * @param msg */ void setProgressMessage(const QString& msg) { progressMessage_ = msg; } /** * Returns the list of files matched during the last scan. * @return The matching file list */ const QStringList& matchedFiles() const { return fileList_; } public slots: /** * Signals the scan process to stop. */ void stop() { stop_ = true; } signals: void progress(int scanned, int matched); void progress(const QString& msg); private: /** * true to follow symbolic links, false (default) to skip them. */ bool followSymLinks_; int scanned_; QStringList fileList_; FileFilter filter_; bool stop_; QString progressMessage_; QSet visitedDirs_; bool scan(const QDir&, bool, bool); }; } } #endif // __CORE_FILESCANNER_H__ kscope-1.9.4/core/locationlistmodel.h0000644000175000001440000000474211156714354017034 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_LOCATIONLISTMODEL_H__ #define __CORE_LOCATIONLISTMODEL_H__ #include "locationmodel.h" namespace KScope { namespace Core { /** * A list model for displaying locations. * This model should be used for all location displays that do not require * a tree-like structure, as its internal storage is more compact and faster * to update. * @author Elad Lahav */ class LocationListModel : public LocationModel { Q_OBJECT public: LocationListModel(QObject* parent = 0); ~LocationListModel(); // LocationMode implementation. void add(const LocationList&, const QModelIndex& index = QModelIndex()); IsEmptyResult isEmpty(const QModelIndex&) const; void clear(const QModelIndex& parent = QModelIndex()); bool locationFromIndex(const QModelIndex&, Location&) const; bool firstLocation(Location&) const; QModelIndex nextIndex(const QModelIndex&) const; QModelIndex prevIndex(const QModelIndex&) const; // QAsbstractItemModel implementation. virtual QModelIndex index(int row, int column, const QModelIndex& parent) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const; private: /** * Result list. */ LocationList locList_; /** * Whether add() was called. * Required by the locationsAdded() method. */ bool locationsAdded_; }; } // namespace Core } // namespace KScope #endif // __CORE_LOCATIONLISTMODEL_H__ kscope-1.9.4/core/progressbar.ui0000644000175000001440000000417511156714354016026 0ustar elahavusers ProgressBar 0 0 250 27 0 0 Form true 0 QLayout::SetNoConstraint 0 0 0 10 0 0 0 Cancel :/images/cancel:/images/cancel 16 16 true cancelButton_ progBar_ kscope-1.9.4/core/engine.h0000644000175000001440000001250511156714354014550 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_ENGINE_H #define __CORE_ENGINE_H #include #include #include "globals.h" namespace KScope { namespace Core { /** * Abstract base-class for cross-reference databases. * This class is the at the heart of KScope's implementation. Its derivations * define methods for retrieving information used to analyse the code base. * @author Elad Lahav */ class Engine : public QObject { Q_OBJECT public: /** * Engine's database status. */ enum Status { /** * Default status. * Do not build or query. */ Unknown, /** * Requires initial build. * No queries can be issued. */ Build, /** * Requires rebuilding. * Queries can be issued in the meantime. */ Rebuild, /** * Up-to-date. * Ready for querying */ Ready }; /** * Class constructor. * @param parent Parent object * @return */ Engine(QObject* parent = NULL) : QObject(parent) {} /** * Class destructor. */ virtual ~Engine() {} /** * Makes the database available for querying. * @param initString Implementation-specific string */ virtual void open(const QString& initString, Callback<>* cb) = 0; /** * Determines the status of the database: whether a build is required and * whether queries can be issued. */ virtual Status status() const = 0; /** * Returns a list of Location structure fields that are filled by the given * query type. * @param The requested query type * @return A list of Location fields */ virtual QList queryFields(Query::Type type) const = 0; /** * Abstract base class for a controllable object. * This allows an engine operation to be stopped. */ struct Controlled { virtual void stop() = 0; }; /** * Represents a single thread of execution in a database. * Engine operations are expected to execute asynchronously. Therefore, * methods of the Engine class that invoke such operations (query and build) * take an Engine::Connection object as a parameter. This object is used to * convey information on the executing operation, including its progress and * results. * From the caller's end, this object can be used to stop an on-going * operation. * @author Elad Lahav */ struct Connection { /** * Struct constructor. */ Connection() : ctrlObject_(NULL) {} /** * @param ctrlObject A controlled object that allows the operation to * be stopped */ void setCtrlObject(Controlled* ctrlObject) { ctrlObject_ = ctrlObject; } /** * Stops the current operation. */ virtual void stop() { if (ctrlObject_) ctrlObject_->stop(); } /** * Called when query data is produced by the engine. * @param locList A location list, holding query results */ virtual void onDataReady(const Core::LocationList& locList) = 0; /** * Called when an engine operation terminates successfully. */ virtual void onFinished() = 0; /** * Called when an engine operation terminates abnormally. */ virtual void onAborted() = 0; /** * Called when an engine operation makes progress. * @param text A message describing the kind of progress made * @param cur The current value * @param total The expected final value */ virtual void onProgress(const QString& text, uint cur, uint total) = 0; protected: /** * An object which can be used to stop the current operation. */ Controlled* ctrlObject_; }; public slots: /** * Starts a query. * @param conn Used for communication with the ongoing operation * @param query The query to execute */ virtual void query(Connection* conn, const Query& query) const = 0; /** * (Re)builds the symbols database. * @param conn Used for communication with the ongoing operation */ virtual void build(Connection*) const = 0; }; /** * A template for configuring engines. * Specialise to provide custom-behaviour for specific engines. */ template struct EngineConfig { static QString name() { return QString(); } static void getConfig(KeyValuePairs& confParams) { (void)confParams; } static void setConfig(const KeyValuePairs& confParams) { (void)confParams; } static QWidget* createConfigWidget(QWidget* parent) { (void)parent; return NULL; } static void configFromWidget(QWidget* widget) { (void)widget; } }; } // namespace Core } // namespace KScope #endif // __CORE_ENGINE_H kscope-1.9.4/core/queryview.cpp0000644000175000001440000001505711156714354015703 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "queryview.h" #include "exception.h" #include "engine.h" #include "progressbar.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent The parent widget * @param type Whether the view works in list or tree modes */ QueryView::QueryView(QWidget* parent, Type type) : LocationView(parent, type), progBar_(NULL), autoSelectSingleResult_(false) { // Query child items when expanded (in a tree view). if (type_ == Tree) { connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(queryTreeItem(const QModelIndex&))); } menu_->addAction(tr("&Rerun Query"), this, SLOT(requery())); } /** * Class destructor. */ QueryView::~QueryView() { } /** * @param query The query to run */ void QueryView::query(const Query& query) { // Delete the model data. locationModel()->clear(QModelIndex()); try { // Get an engine for running the query. Engine* eng; if ((eng = engine()) != NULL) { // Run the query. query_ = query; locationModel()->setColumns(eng->queryFields(query_.type_)); eng->query(this, query_); } } catch (Exception* e) { e->showMessage(); delete e; } } /** * Creates an XML representation of the view, which can be used for storing the * model's data in a file. * Adds query information to the representation created by * LocationView::toXML(). * @param doc The XML document object to use * @param viewElem The element representing the view */ void QueryView::toXML(QDomDocument& doc, QDomElement& viewElem) const { // Store query information. QDomElement queryElem = doc.createElement("Query"); queryElem.setAttribute("type", QString::number(query_.type_)); queryElem.setAttribute("flags", QString::number(query_.flags_)); queryElem.appendChild(doc.createCDATASection(query_.pattern_)); viewElem.appendChild(queryElem); LocationView::toXML(doc, viewElem); } /** * Loads a query view from an XML representation. * @param root The root element for the query's XML representation */ void QueryView::fromXML(const QDomElement& viewElem) { // Get query information. QDomElement queryElem = viewElem.elementsByTagName("Query").at(0).toElement(); if (queryElem.isNull()) return; query_.type_ = static_cast (queryElem.attribute("type").toUInt()); query_.flags_ = queryElem.attribute("flags").toUInt(); query_.pattern_ = queryElem.childNodes().at(0).toCDATASection().data(); LocationView::fromXML(viewElem); } /** * Called by the engine when results are available. * Adds the list of locations to the model. * @param locList Query results */ void QueryView::onDataReady(const LocationList& locList) { locationModel()->add(locList, queryIndex_); } /** * Displays progress information in a progress-bar at the top of the view. * @param text Progress message * @param cur Current value * @param total Expected final value */ void QueryView::onProgress(const QString& text, uint cur, uint total) { // Create the progress-bar widget, if it does not exist. if (!progBar_) { progBar_ = new ProgressBar(this); connect(progBar_, SIGNAL(cancelled()), this, SLOT(stopQuery())); progBar_->show(); } // Update progress information in the progress bar. progBar_->setLabel(text); progBar_->setProgress(cur, total); if (!isVisible()) emit needToShow(); } /** * Called by the engine when a query terminates normally. */ void QueryView::onFinished() { // Handle an empty result set. if (locationModel()->rowCount(queryIndex_) == 0) locationModel()->add(LocationList(), queryIndex_); // Destroy the progress-bar, if it exists. if (progBar_) { delete progBar_; progBar_ = NULL; } // Adjust column sizes. resizeColumns(); // Auto-select a single result, if required. Location loc; if (autoSelectSingleResult_ && locationModel()->rowCount(queryIndex_) == 1 && locationModel()->firstLocation(loc)) { emit locationRequested(loc); } else { setCurrentIndex(QModelIndex()); if (!isVisible()) emit needToShow(); } } /** * Called by the engine when a query terminates abnormally. */ void QueryView::onAborted() { // Destroy the progress-bar, if it exists. if (progBar_) { delete progBar_; progBar_ = NULL; } } /** * Called when the "Cancel" button is clicked in the progress-bar. * Informs the engine that the query process should be stopped. */ void QueryView::stopQuery() { stop(); } /** * Called when a tree item is expanded. * If this item was not queried before, a query is performed. * @param index The expanded item (proxy index) */ void QueryView::queryTreeItem(const QModelIndex& index) { // Query previously-non-queried items only. QModelIndex srcIndex = proxy()->mapToSource(index); if (locationModel()->isEmpty(srcIndex) != LocationModel::Unknown) return; // Get the location information from the index. Location loc; if (!locationModel()->locationFromIndex(srcIndex, loc)) return; // Run a query on this location. try { Engine* eng; if ((eng = engine()) != NULL) { queryIndex_ = srcIndex; eng->query(this, Query(query_.type_, loc.tag_.scope_)); } } catch (Exception* e) { e->showMessage(); delete e; } } /** * Runs the current query again. */ void QueryView::requery() { // Do nothing if there is no valid query associated with this view. if (query_.type_ == Query::Invalid) return; // For a list view, just re-execute the query. if (type_ == List) { query(query_); return; } // Tree view: rerun the current branch only. QModelIndex srcIndex = proxy()->mapToSource(menuIndex_); locationModel()->clear(srcIndex); queryTreeItem(menuIndex_); } } // namespace Core } // namespace KScope kscope-1.9.4/core/locationmodel.cpp0000644000175000001440000001141311156714354016464 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "locationmodel.h" #include "strings.h" #include "images.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent Parent object */ LocationModel::LocationModel(QObject* parent) : QAbstractItemModel(parent) { } /** * Class destructor. */ LocationModel::~LocationModel() { } /** * Sets a new common root path for display purposes. * @param path The new path to set */ void LocationModel::setRootPath(const QString& path) { QString actPath = path; if (path == "/") actPath = QString(); else if (!path.endsWith("/")) actPath += "/"; if (actPath != rootPath_) { rootPath_ = actPath; reset(); } } /** * Provides information for constructing a header when this model is displayed * in a view. * @param section Corresponds to the column number * @param orient Horizontal or vertical header * @param role How to interpret the information * @return For a horizontal header with a display role, returns the column * title; An empty variant for all other type */ QVariant LocationModel::headerData(int section, Qt::Orientation orient, int role) const { if (orient != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); return columnText(colList_[section]); } /** * Returns the number of columns for the children of the given parent. * @param parent The parent index * @return The size of the column list for all the children of the root index */ int LocationModel::columnCount(const QModelIndex& parent) const { (void)parent; return colList_.size(); } #ifndef QT_NO_DEBUG /** * Debugging facility. * Ensures the correctness of the model. * @param parentIndex The root index to verify */ void LocationModel::verify(const QModelIndex& parentIndex) const { for (int i = 0; i < rowCount(parentIndex); i++) { QModelIndex childIndex = index(i, 0, parentIndex); Q_ASSERT(parent(childIndex) == parentIndex); verify(childIndex); } } #endif /** * Extracts data from a location object, for the given column index. * @param loc The location object * @param col The requested column * @return Matching location data, QVariant() if the column is invalid */ QVariant LocationModel::locationData(const Location& loc, uint col, int role) const { switch (role) { case Qt::DecorationRole: if ((colList_[col] == Location::TagName) && (loc.tag_.type_ != Tag::UnknownTag)) { return Images::tagIcon(loc.tag_.type_); } return QVariant(); case Qt::DisplayRole: break; default: return QVariant(); } switch (colList_[col]) { case Location::File: // File path. // Replace root prefix with "$". if (!rootPath_.isEmpty() && loc.file_.startsWith(rootPath_)) return QString("$/") + loc.file_.mid(rootPath_.length()); return loc.file_; case Location::Line: // Line number. return loc.line_; case Location::Column: // Column number. return loc.column_; case Location::TagName: // Tag name. return loc.tag_.name_; case Location::TagType: // Tag type. return Strings::tagName(loc.tag_.type_); case Location::Scope: // Scope. return loc.tag_.scope_; case Location::Text: // Line text. return loc.text_; } return QVariant(); } /** * Creates a column header title for the given column. * @param col The column for which the title is requested * @return A string describing the column */ QString LocationModel::columnText(Location::Fields col) const { switch (col) { case Location::File: return tr("File"); case Location::Line: return tr("Line"); case Location::Column: return tr("Column"); case Location::TagName: return tr("Tag"); case Location::TagType: return tr("Type"); case Location::Scope: return tr("Scope"); case Location::Text: return tr("Text"); } return ""; } } // namespace Core } // mamespace KScope kscope-1.9.4/core/textfilterdialog.cpp0000644000175000001440000000721311156714354017210 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "textfilterdialog.h" namespace KScope { namespace Core { /** * Class constructor. * @param re The regular expression to use by default * @param parent Parent widget */ TextFilterDialog::TextFilterDialog(const QRegExp& re, QWidget* parent) : QDialog(parent), Ui::TextFilterDialog() { setupUi(this); // Show the regular expression pattern. patternEdit_->setText(re.pattern()); // Set the type of filter to use. if (re.isEmpty()) { // Special case: empty QRegExp. // We want the default to be a fixed-string match, while a QRegExp() // constructor defaults to a regular expression. stringButton_->setChecked(true); } else { // Non-empty QRegExp. // Use the type set for the object. switch (re.patternSyntax()) { case QRegExp::FixedString: stringButton_->setChecked(true); break; case QRegExp::RegExp: case QRegExp::RegExp2: regExpButton_->setChecked(true); break; case QRegExp::Wildcard: simpRegExpButton_->setChecked(true); break; } } // Determine whether the filter is case-sensitive. caseSensitiveCheck_->setChecked(re.caseSensitivity() == Qt::CaseSensitive); } /** * Class destructor. */ TextFilterDialog::~TextFilterDialog() { } /** * Populates the "Filter By" combo-box. * @param pairs Option names and values for the combo-box */ void TextFilterDialog::setFilterByList(const KeyValuePairs& pairs) { KeyValuePairs::ConstIterator itr; for (itr = pairs.begin(); itr != pairs.end(); ++itr) filterByCombo_->addItem(itr.key(), itr.value()); } /** * Selects an item in the "Filter By" combo-box. * @param value The value by which the item is selected */ void TextFilterDialog::setFilterByValue(const QVariant& value) { int index = filterByCombo_->findData(value); if (index >= 0) filterByCombo_->setCurrentIndex(index); } /** * Generates a QRegExp object from the parameters of the dialogue. * @return The generated QRegExp object */ QRegExp TextFilterDialog::filter() const { // Determine the type of filter to use. QRegExp::PatternSyntax type; if (stringButton_->isChecked()) type = QRegExp::FixedString; else if (regExpButton_->isChecked()) type = QRegExp::RegExp; else if (simpRegExpButton_->isChecked()) type = QRegExp::Wildcard; // Determine case sensitivity. Qt::CaseSensitivity cs = caseSensitiveCheck_->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive; // Create and return the object. return QRegExp(patternEdit_->text(), cs, type); } /** * @return The data stored in the current index of the "Filter By" combo */ QVariant TextFilterDialog::filterByValue() const { return filterByCombo_->itemData(filterByCombo_->currentIndex()); } } // namespace Core } // namespace KScope kscope-1.9.4/core/progressbar.h0000644000175000001440000000277611156714354015645 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_PROGRESSBAR_H #define __CORE_PROGRESSBAR_H #include #include "ui_progressbar.h" namespace KScope { namespace Core { /** * A stand-alone progress bar with a label and cancel button. * @author Elad Lahav */ class ProgressBar : public QFrame, private Ui::ProgressBar { Q_OBJECT public: ProgressBar(QWidget* parent = 0); ~ProgressBar(); public slots: void setProgress(uint, uint); void setLabel(const QString&); signals: void cancelled(); }; } // namespace Core } // namespace KScope #endif // COREPROGRESSBAR_H kscope-1.9.4/core/textfilterdialog.ui0000644000175000001440000000665611156714354017055 0ustar elahavusers TextFilterDialog 0 0 346 268 Dialog Pattern Filter By 0 0 Options String Regular Expression Simplified Regular Expression Case sensitive stringButton_ regExpButton_ simpRegExpButton_ caseSensitiveCheck_ Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() TextFilterDialog accept() 248 254 157 274 buttonBox rejected() TextFilterDialog reject() 316 260 286 274 kscope-1.9.4/core/locationview.h0000644000175000001440000001117011156714354016003 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_LOCATIONVIEW_H__ #define __CORE_LOCATIONVIEW_H__ #include #include #include #include #include #include #include "globals.h" #include "locationmodel.h" namespace KScope { namespace Core { /** * A proxy model used by LocationView. * @author Elad Lahav */ class LocationViewProxyModel : public QSortFilterProxyModel { Q_OBJECT public: /** * Class constructor. * @param parent Parent object */ LocationViewProxyModel(QObject* parent) : QSortFilterProxyModel(parent) {} /** * Class destructor. */ ~LocationViewProxyModel() {} /** * Determines if the given index has children. * Used to display an expansion button beside items which either have * children, or for which the state is still unknown (for on-demand * population of the model). * @param parent The parent index * @return true to display an expansion button, false otherwise */ bool hasChildren(const QModelIndex& parent = QModelIndex()) const { LocationModel* model = static_cast(sourceModel()); if (model->isEmpty(mapToSource(parent)) == LocationModel::Unknown) return true; return QSortFilterProxyModel::hasChildren(parent); } }; /** * A view for displaying LocationModel models. * Adds filtering and save/restore capabilities to a standard QTreeView. * @author Elad Lahav */ class LocationView : public QTreeView { Q_OBJECT public: /** * The view can work in either list or tree modes. */ enum Type { List, Tree }; LocationView(QWidget*, Type type = List); ~LocationView(); void resizeColumns(); virtual void toXML(QDomDocument&, QDomElement&) const; virtual void fromXML(const QDomElement&); /** * @return The type of the view */ Type type() const { return type_; } /** * @return The proxy model */ inline LocationViewProxyModel* proxy() { return static_cast(model()); } /** * @return The proxy model */ inline const LocationViewProxyModel* proxy() const { return static_cast(model()); } /** * @return The location model for this view */ inline LocationModel* locationModel() { return static_cast(proxy()->sourceModel()); } /** * @return The location model for this view */ inline const LocationModel* locationModel() const { return static_cast(proxy()->sourceModel()); } public slots: void selectNext(); void selectPrev(); signals: /** * Emitted when a location item is selected. * @param loc The location descriptor */ void locationRequested(const Core::Location& loc); /** * Emitted when the view needs to be visible. * This is useful for creating containers that only become visible when * there is something to show in the view (either progress or results). */ void needToShow(); /** * Emitted when the filter on the proxy model is changed. * @param filtered true if a filter is currently applied, false otherwise */ void isFiltered(bool filtered); protected: /** * Whether the view is in list or tree modes. */ Type type_; /** * A context menu for the view widget. */ QMenu* menu_; /** * The proxy index for which the context menu was displayed. */ QModelIndex menuIndex_; virtual void contextMenuEvent(QContextMenuEvent*); virtual void locationToXML(QDomDocument&, QDomElement&, const QModelIndex&) const; virtual void locationFromXML(const QDomElement&, const QModelIndex&); protected slots: void requestLocation(const QModelIndex&); void promptFilter(); void clearFilter(); }; } // namespace Core } // namespace KScope #endif // __CORE_LOCATIONVIEW_H__ kscope-1.9.4/core/parser.h0000644000175000001440000002411311156714354014575 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __PARSER_PARSER_H__ #define __PARSER_PARSER_H__ #include #include namespace KScope { namespace Parser { /** * Possible results when matching input to a parser object. */ enum ParseResult { /** Input cannot be matched by the parser. */ NoMatch, /** Potential match, but more input is required. */ PartialMatch, /** Input was matched by the parser. */ FullMatch }; /** * A list of values captured during parsing. * The use of a QVector container allows us to pre-allocate the list when the * number of captured values is known (which is true in most cases, the * exception being parsers that include a Kleene-star expression). */ struct CapList { /** * The actual storage. */ QVector caps_; /** * The number of used positions in the vector. */ int used_; /** * Default constructor. * Used when the number of captured values is not known in advance. */ CapList() : caps_(), used_(0) {} /** * Constructor. * Used when the number of captured values is known in advance. * @param size The number of values that can be captured by the parser */ CapList(int size) : caps_(size), used_(0) {} /** * Appends a value to the vector. * If the vector was pre-allocated, the value is set at the next available * position (rather than growing the vector, which is the default). * @param var The value to append * @return A reference to this object */ CapList& operator<<(const QVariant& var) { if (used_ < caps_.size()) caps_[used_++] = var; else caps_ << var; return *this; } /** * Provides random access to the values in the vector. * @param pos The position to get * @return The value at the given position */ const QVariant& operator[](int pos) const { return caps_[pos]; } /** * @return The size of the vector */ int size() const { return caps_.size(); } }; /** * Specialisation for known sizes. */ template struct SizedCapList : public CapList { SizedCapList() : CapList(S) {} }; /** * Specialisation for unknown sizes (represented by -1). */ template<> struct SizedCapList<-1> : public CapList { SizedCapList() : CapList() {} }; /** * Combines two numbers, each representing the number of captured values in a * parser class. * If both values are non-negative, the result is the sum of the two numbers. * Otherwise, the result is -1, representing an "unknown" value, which is the * case in a parser with a Kleene-star operator. */ template struct AddCapCount { static const int result_ = A + B; }; /** * Specialisation for the case where the first number is negative. */ template struct AddCapCount<-1, B> { static const int result_ = -1; }; /** * Specialisation for the case where the first number is negative. */ template struct AddCapCount { static const int result_ = -1; }; template struct Concat; template struct Kleene; /** * Syntactic-sugar operators for building parsers out of the basic blocks. * Each parser class T should inherit from Operators. */ template struct Operators { template Concat operator<<(const Exp2T&) const; Kleene operator*() const; }; /** * Matches a fixed-string. */ struct Literal : public Operators { /** * Class constructor. * @param str The string to match. */ Literal(const QString& str) : str_(str) {} /** * Matches the object's string with a prefix of the input. * @param input The input string * @param pos The current position in the input string * @param caps An ordered list of captured values * @return true if the input has a mathcing prefix, false otherwise */ ParseResult match(const QString& input, int& pos, CapList& caps) const { (void)caps; #ifdef DEBUG_PARSER qDebug() << "Literal::match" << input.mid(pos) << str_; #endif // If the input is shorter than the expected string, that it can be at // most a partial match. if (input.length() < str_.length()) return str_.startsWith(input) ? PartialMatch : NoMatch; // Input is longer than expected string, so it is either a full match or // no match. if (input.mid(pos, str_.length()) == str_) { #ifdef DEBUG_PARSER qDebug() << str_; #endif pos += str_.length(); return FullMatch; } return NoMatch; } static const int capCount_ = 0; private: /** The string to match. */ const QString str_; }; /** * Captures a base-10 numeric value. */ struct Number : public Operators { /** * Matches a non-empty sequence of digits, up to the first non-digit * character (or the end of the input). * @param input The input string * @param pos The current position in the input string * @param caps An ordered list of captured values * @return true if matched a number, false otherwise */ ParseResult match(const QString& input, int& pos, CapList& caps) const { int digit, number = 0; bool foundNumber = false; #ifdef DEBUG_PARSER qDebug() << "Number::match" << input.mid(pos); #endif // Iterate to the end of the input. while (pos < input.size()) { // Stop if a non-digit character is found. if ((digit = input[pos].digitValue()) == -1) { // Check if any input was consumed. if (!foundNumber) return NoMatch; // Found a number. #ifdef DEBUG_PARSER qDebug() << number; #endif caps << number; return FullMatch; } // At least one digit. // Update the captured numeric value, the position and indicate that // a number has been found. number = (number * 10) + digit; pos++; foundNumber = true; } // Ran out of input characters. return PartialMatch; } static const int capCount_ = 1; }; /** * Captures a string delimited by a single character. * The default delimiter causes the string to match to the end of the input. */ template struct String : public Operators< String > { String(DelimT delim) : delim_(delim) {} /** * Matches a string up to the object's delimiter. * @param input The input string * @param pos The current position in the input string * @param caps An ordered list of captured values * @return true if matched a non-empty string, false otherwise */ ParseResult match(const QString& input, int& pos, CapList& caps) const { #ifdef DEBUG_PARSER qDebug() << "String::match" << input.mid(pos); #endif if (input.isEmpty()) return PartialMatch; // Find an occurrence of the delimiter. int delimPos = input.indexOf(delim_, pos); if (delimPos == -1) return PartialMatch; // Check for empty strings. if (!AllowEmpty && delimPos == pos) return NoMatch; // Update position and captured values list. #ifdef DEBUG_PARSER qDebug() << input.mid(pos, delimPos - pos); #endif caps << input.mid(pos, delimPos - pos); pos = delimPos; return FullMatch; } static const int capCount_ = 1; private: DelimT delim_; }; /** * Swallows whitespace. */ struct Whitespace : public Operators { /** * Matches a (possibly empty) sequence of any space characters. * @param input The input string * @param pos The current position in the input string * @param caps An ordered list of captured values * @return Always true */ ParseResult match(const QString& input, int& pos, CapList& caps) const { (void)caps; #ifdef DEBUG_PARSER qDebug() << "Whitespace::match" << input; #endif while ((pos < input.size()) && (input[pos].isSpace())) pos++; return FullMatch; } static const int capCount_ = 0; }; /** * Concatenates two parsers. * Matches input that is matched first by one parser, and then by the other. */ template struct Concat : public Operators< Concat > { Concat(Exp1T exp1, Exp2T exp2) : exp1_(exp1), exp2_(exp2) {} ParseResult match(const QString& input, int& pos, CapList& caps) const { ParseResult result = exp1_.match(input, pos, caps); if (result == FullMatch) return exp2_.match(input, pos, caps); return result; } static const int capCount_ = AddCapCount::result_; private: Exp1T exp1_; Exp2T exp2_; }; /** * A Kleene-star closure. * Matches input matched by zero or more instances of a parser. */ template struct Kleene : public Operators< Kleene > { Kleene(ExpT exp) : exp_(exp) {} ParseResult match(const QString& input, int& pos, CapList& caps) const { ParseResult result; while ((result = exp_.match(input, pos, caps)) == FullMatch) ; if (result == PartialMatch) return PartialMatch; return FullMatch; } private: ExpT exp_; }; /** * Implements the concatenation operator (<<) for building parsers. */ template template Concat Operators::operator<<(const Exp2T& exp2) const { return Concat(*static_cast(this), exp2); } /** * Implements the Kleene-star operator (*) for building parsers. */ template Kleene Operators::operator*() const { return Kleene(*static_cast(this)); } } // namespace Parser } // namespace KScope #endif // __PARSER_PARSER_H__ kscope-1.9.4/core/queryview.h0000644000175000001440000001023611156714354015342 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_QUERYVIEW_H__ #define __CORE_QUERYVIEW_H__ #include "locationview.h" #include "globals.h" #include "engine.h" namespace KScope { namespace Core { class Engine; class ProgressBar; /** * A view for displaying query results. * Results can be displayed either as either a list or a tree (for call trees). * Since the class implements Engine::Connection, an object of this type can be * passed to an engine's query() method. Progress will be displayed in the * form of a progress-bar at the top of the view. * There are two ways in which the widget can be used to view query results: * 1. Constructing the widget and passing it to an engine's query() method; * 2. Using the widget's own query() method. * For the latter to work, engine() needs to be specialised. This is a * compromise between functionality and good design. Functionality requires an * engine to be available to the widget, in order to be able to refresh queries * and expand tree items by itself. Good design requires that we do not keep * an embedded engine object/pointer in this class. * Note that the tree view can only work with option 2, as the queryTreeItem() * method, connected to the expanded() signal, uses the engine to query run a * query on a child item. * @author Elad Lahav */ class QueryView : public LocationView, public Engine::Connection { Q_OBJECT public: QueryView(QWidget*, Type type = List); ~QueryView(); void query(const Query&); virtual void toXML(QDomDocument&, QDomElement&) const; virtual void fromXML(const QDomElement&); /** * In the case the query returns only a single location, determines whether * this location should be selected automatically. * @param select true to select a single result, false otherwise */ void setAutoSelectSingleResult(bool select) { autoSelectSingleResult_ = select; } // Engine::Connection implementation. virtual void onDataReady(const LocationList&); virtual void onFinished(); virtual void onAborted(); virtual void onProgress(const QString&, uint, uint); protected: /** * Used by the query() method to launch queries on the engine. * The default implementation returns NULL, which means that a query cannot * be started directly. Re-implement to allow the widget to handle its own * queries. * @return The engine to use for running queries */ virtual Engine* engine() { return NULL; } private: /** * The query associated with this view. * This can be used, e.g., for re-running the query from within the view. */ Query query_; /** * The index under which query results should be put. */ QModelIndex queryIndex_; /** * A progress-bar for displaying query progress information. * This widget is created upon the first reception of progress information, * and destroyed when the query terminates. */ ProgressBar* progBar_; /** * In the case the query returns only a single location, determines whether * this location should be selected automatically. * @param select true to select a single result, false otherwise */ bool autoSelectSingleResult_; private slots: void stopQuery(); void queryTreeItem(const QModelIndex&); void requery(); }; } // namespace Core } // namespace KScope #endif // __CORE_QUERYVIEW_H__ kscope-1.9.4/core/progressbar.cpp0000644000175000001440000000360311156714354016166 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "progressbar.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent Parent widget */ ProgressBar::ProgressBar(QWidget* parent) : QFrame(parent), Ui::ProgressBar() { // Setup user interface. setFrameShape(QFrame::StyledPanel); setupUi(this); // Emit the cancelled() signal when the cancel button is clicked. connect(cancelButton_, SIGNAL(clicked()), this, SIGNAL(cancelled())); } /** * Class destructor. */ ProgressBar::~ProgressBar() { } /** * Updates the progress values. * @param cur New current value * @param total Expected final value */ void ProgressBar::setProgress(uint cur, uint total) { progBar_->setRange(0, total); progBar_->setValue(cur); } /** * Changes the text inside the progress-bar. * @param text The new text to show */ void ProgressBar::setLabel(const QString& text) { progBar_->setFormat(text + " %p%"); } } // namespace Core } // namespace KScope kscope-1.9.4/core/statemachine.h0000644000175000001440000001531511156714354015752 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __PARSER_STATEMACHINE_H__ #define __PARSER_STATEMACHINE_H__ #include #include "parser.h" namespace KScope { namespace Parser { /** * My attempt at a generic, fancy-looking, state-machine. * The main goal is to be able to describe a state machine implementation as * simply and elegantly as possible. * The machine is a set of states and a transition function. Given an input * string, the current state is checked for all outgoing edges, which hold * statically built parser objects. If the input string is matched by the * parser, that edge's in-vertex is set as the current state. * @author Elad Lahav */ class StateMachine { public: struct TransitionBase; /** * A single state in the machine. * The entire logic of the state machine is implemented in the list of * Transition objects held by each state. */ struct State { State(QString name = "") : name_(name) {} State(const State& other) : name_(other.name_), transList_(other.transList_) {} bool isError() const { return transList_.isEmpty(); } QString name_; QList transList_; }; /** * Default action type for matching transitions. * Does nothing. */ struct NoAction { void operator()(const CapList& caps) const { (void)caps; } }; /** * Abstract base class for transitions. * Since transition objects are created at compile time, we need this * base class in order to be able to specify a list of pointers to * transitions in the State class. */ struct TransitionBase { TransitionBase(const State& nextState) : nextState_(nextState) {} virtual int matches(const QString& input, int pos) const = 0; const State& nextState_; }; /** * A transition rule in a state machine. * Transitions are associated with states, and each has the form of * . If an input is matched by the parser, then * the action is taken and the state machine should advance to the next * state. */ template struct Transition : public TransitionBase { Transition(const State& nextState, const ParserT& parser) : TransitionBase(nextState), parser_(parser) {} Transition(const State& nextState, const ParserT& parser, ActionT action) : TransitionBase(nextState), parser_(parser), action_(action) {} /** * Determines if a transition should be taken. * @param input The input to match against * @return The number of characters matched by the parser if the input * matches, -1 if a partial match was found, -2 on a parse * error */ int matches(const QString& input, int pos) const { SizedCapList caps; switch (parser_.match(input, pos, caps)) { case NoMatch: return -2; case PartialMatch: return -1; case FullMatch: action_(caps); return pos; } return 0; } /** * The parser used to match input. */ ParserT parser_; /** * The action to take if input matches. */ ActionT action_; }; /** * Class constructor. */ StateMachine() : curState_(&initState_) {} /** * Class destructor. */ ~StateMachine() { while (!transList_.isEmpty()) delete transList_.takeFirst(); } /** * Parses the given input using the state machine. * When the method returns, the input string is adjusted to contain only * the part of the input that was not parsed (in case of a partial parse * match). * @param input The input to parse * @return true if parsing was successful, false otherwise */ bool parse(QString& input) { // Return immediately if in an error state. if (curState_->isError()) { qDebug() << "Error state!"; return false; } int pos = 0; while (pos < input.length()) { ParseResult result = NoMatch; // Iterate over the list of transitions. QList::ConstIterator itr; for (itr = curState_->transList_.begin(); itr != curState_->transList_.end(); ++itr) { // Match the input using the transition's parser. int newPos = (*itr)->matches(input, pos); if (newPos >= 0) { // Match, consume input and move to the next state. pos = newPos; curState_ = &(*itr)->nextState_; result = FullMatch; #ifdef DEBUG_PARSER qDebug() << "Parse match, next state is" << curState_->name_; #endif break; } else if (newPos == -1) { // Partial match, try other rules for a full match. result = PartialMatch; } } // Abort if no rule matched. if (result == NoMatch) { qDebug() << "Parse error!" << curState_->name_ << input.mid(pos); curState_ = &errorState_; return false; } // Stop if only a partial match was found. if (result == PartialMatch) break; } // Wait for more input. input = input.mid(pos); return true; } /** * Sets the current state of the machine. * @param state The new state */ void setState(const State& state) { curState_ = &state; } /** * Sets the default state as the current one. */ void reset() { curState_ = &initState_; } template void addRule(State& from, const ParserT& parser, const State& to, const ActionT& action) { typedef Transition TransT; TransT* trans = new TransT(to, parser, action); from.transList_.append(trans); transList_.append(trans); } template void addRule(State& from, const ParserT& parser, const State& to) { typedef Transition TransT; TransT* trans = new TransT(to, parser); from.transList_.append(trans); transList_.append(trans); } protected: State initState_; private: const State* curState_; State errorState_; QList transList_; }; } // namespace Parser } // namespace KScope #endif // __PARSER_STATEMACHINE_H__ kscope-1.9.4/core/filefilter.h0000644000175000001440000001077011156714354015432 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_FILEFILTER_H__ #define __CORE_FILEFILTER_H__ #include namespace KScope { namespace Core { /** * An advanced include/exclude file filter. * The filter is represented as a list of rules, each can classified as an * inclusion or exclusion rule. When matching a path name, the filter compares * the path with each of the entries in order, returning a decision based on * the first matching rule. * A filter can be created from a string, formatted as following: * - Rules are separated by semicolons * - Each rule is given as a simplified (shell-style) regular expression * - By default a rule is classified as an inclusion one * - To create an exclusion rule, prefix the expression with a minus sign (-) * @author Elad Lahav */ class FileFilter { public: /** * Default constructor. */ FileFilter() {} /** * Class constructor. * Creates a filter out of the given semicolon-delimited string. * @param filter The filter string * @return */ FileFilter(const QString& filter) { parse(filter); } /** * Determines whether the given path is matched by the filter. * Iterates over the list of rules. The first rule whose pattern matches * the path name is used to determine whether the path is accepted * (including rule) or rejected (excluding rule). * @param path The path name to check * @param noMatchResult The value to return in case no rule matches the * path * @return true if the path is accepted by the filter, false otherwise */ bool match(const QString& path, bool noMatchResult) const { QList::ConstIterator itr; for (itr = ruleList_.begin(); itr != ruleList_.end(); ++itr) { if ((*itr).exp_.exactMatch(path)) return (((*itr).type_ == Rule::Include) ? true : false); } return noMatchResult; } /** * Creates a semicolon delimited representation of the filter. * @return The filter as a string */ QString toString() const { QString result; QList::ConstIterator itr; for (itr = ruleList_.begin(); itr != ruleList_.end(); ++itr) { if ((*itr).type_ == Rule::Exclude) result += "-"; result += (*itr).exp_.pattern() + ";"; } return result; } private: /** * Represents a single rule in the filter. */ struct Rule { enum Type { Include, Exclude }; /** * Struct constructor. * Creates a simplified regular expression out of the given pattern, * and determines whether it is an inclusion or exclusion pattern based * on the existence of a "-" prefix. * @param pattern Simplified regular expression pattern */ Rule(const QString& pattern) { exp_.setPatternSyntax(QRegExp::Wildcard); if (pattern.startsWith("-")) { exp_.setPattern(pattern.mid(1)); type_ = Exclude; } else { exp_.setPattern(pattern); type_ = Include; } } /** * The simplified regular expression to match against. */ QRegExp exp_; /** * Whether this rule is for including or excluding files. */ Type type_; }; /** * The filter, represented as an ordered list of rules. */ QList ruleList_; /** * Converts a semicolon-delimited string into a list of rules. * @param filter The filter string to parse */ void parse(const QString& filter) { // Split the filter string to get a list of patterns. QStringList patterns = filter.split(';', QString::SkipEmptyParts); // Create a rule for each pattern. QStringList::Iterator itr; for (itr = patterns.begin(); itr != patterns.end(); ++itr) ruleList_.append(Rule(*itr)); } }; } } #endif // __CORE_FILEFILTER_H__ kscope-1.9.4/core/images/0000755000175000001440000000000011156714402014366 5ustar elahavuserskscope-1.9.4/core/images/typedef.gif0000644000175000001440000000211011156714354016515 0ustar elahavusersGIF89aç¼ ¯¼ °¼!¯¼!°½"°½#°½%±¾(²¿(²¿)²¿*³¿+³¿,³À-´À/´Á1µÁ2µÂ4¶Ã6¶Ã7¸Ã8·Ä:¸Ã<¹Ä<¹Å=ºÅA»ÆA»ÆB»ÆB¼ÇC¼ÇD¼ÇE¼ÈG½ÉK¾ÉN¿ÉNÀÊOÀÊPÀËQÁËRÁËTÁËUÁÌUÂÍWÃÌZÃÍ[ÄÎ[ÄÍ\ÅÎ\ÄÎ]ÅÏ_ÅÏ_ÆÏ`ÆÐaÇÏbÆÐcÈÑdÈÑgÉÒiÉÓkÊÒlÊÓmËÓoËÔoËÔpÌÓqÌÔqÌÔrÌÔrÍÕuÍÖvÎÖwÏ×xÏ×|ÐØ}ÐÙ~ÑÙÑÙ‚ÓÙƒÓÚ…ÓÚ†ÓÛ‡ÔÛˆÕÛ‰ÕÜ‹ÕÜŽÖÞŽ×Ý×Þ’ØÞ“Øß“ØÞ”Øß•Øß•Ùß–Ùß—Úà˜Úà™Úá™Úá›ÛâÜâŸÝâ Ýã¢Ýä¢Þã¤Þä¤Þä¤ßä¥ßä§àå§àå©àåªáæ­âç¯âç°âç±äè³äè´äéµåé·åê¹æêºæë¼çì¿èìÀèìÀéìÁéíÄêíÅéïÇëïÊìðÍíñÑîòÔïó×ñÿÿÿ¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯¼ ¯!ù ÿ,þÿ H° Áƒÿ²¤™sGM"- ˆPŸ:lÀPY"äE‰o Ú#M—)I~ØHÂÁ6†å‰cF $PX@c¨\‹Ký@‚ƒ¼8žth ˆYkqî_ÿ&%  <¹d¨Å ‚†Ì›«×ǰ Vç.ùµÄùÉ߯—øïógþ";kscope-1.9.4/core/images/union.gif0000644000175000001440000000112211156714354016207 0ustar elahavusersGIF89aæÃç¤Â椵՘Æé©Ãæ£Ã壴ՒµÕ’´Õ“´Ô’µÔ“ÀâšÀá™ÀášµÔ’½ß¼Þ³Ó‹³ÒŠ±Ñƒ½Þ³Ò‰¯Ë‡µÐŽÃàœ²Ñƒ²ËÄßœ·×€¶Ï¸×€¯Çƒ°Ík°Îl±Îl°Íl¯Ìn¯ÌoªÁv±Ík·Ðw·Ðx®q¤¹e£¸g™§n°Æi” j¶Å{ÀІÁІºÉu¶Ä{´Ám»Éu¾Ê{¶Ár“gŒ‘c‹W‹Ž^Ž‘f‰Œc“kÜß´×Ù«×Ù¬ÚܯØÚ°¼½jˆ‰TÊˈÉʇÙÚ°¶µ`¶¶`»ºe»»e··eÃÂvÂÁzÆÅÆÅƒÆÆƒÆÆ„ÉɇÊʈÁ¾sÁ¿sÃÁz„‚^{O‚W†ƒb¹¯Tº°Vº±[¼³]zP¸©L¸©M{sU|tXxmJwmKzpQtfHsfIuiMvkQwlTtgNthPÿÿÿ!ùq,¯€q‚ƒ„…†@QadaQ@†‚VE21EG†H7 7U„CM ]f n? LCƒO3Zem=6Oƒ_)\i&l<(_ƒc ![g"#+jF#'cƒ^.$bh$$,k;%.^ƒW5:o*-o/5XƒBJ>pÿ9"TX„ PpÀ@R MqBã‚€0œPy'I0dÀ@!±¤É’;kscope-1.9.4/core/images/enum.gif0000644000175000001440000000214011156714354016024 0ustar elahavusersGIF89aç£fSgSgThThUhUiWjWlZmZm[m[n\o\q^#q_#r`$r`%ra%sa&sb&sb'tb'tc(uc)ud)ud*wf,yi0zi1zj1zk2{k4|k3|k4}m6~m7~n8~o8~o9o9p9q;r<‚r=‚s=ƒs>ƒt@„t@…vB‡xE‡xFˆxE‡yFˆyGˆzGˆzH‰zG‰zH‰{HŠ{J‹|KŽPŽ€PŽ€QŽQQRR‚R‚R•ˆZ•ˆ[–ˆ\–‰\–‰]—‰\–Š]™a›d›eœdœeœfœfgœ‘fŸ“j “k ”k¡•n¢–n¢–p¢—p£—o£—q£˜q¤˜q§œv§œw§w§x¨y©žz©ŸzªŸ{ª |®¤‚¯¦„°¦„±§†³©‰´ªŠ¶­¶®Ž·®½µ™¾µ™¿¶šÀ¸Ã»¢Ã»£Ä¼£Æ¿§ÈÁªÉ«ÉÂ¬ÌÆ°ÎÈ´ÏɵÑ˸Ò̹ÔμÕоÖÑ¿ÚÕÅÛÖÇÛ×ÈÜ×ÉßÛÎàÜÏáÝÐâÞÒâßÓäàÕåá×åâ×æãØæãÙèåÛèåÜéçÞëèàíêãíëäñïéñðêôòîôóîùøöúúøüüûýýüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù ÿ,þÿ H° Áƒÿ |1£fK(ÄgŽ›4_ª0!¢ãĉeê䤌•%Fv¸¡ÁA2v……‰J’"9ZˆÈР€‚WèB”hÔ%%Cp°P ¾‰ãæL¡Q•„Üh‚ç¨Q>‘ÓæL—A£(å`ñÂI(#À†å—)FIbC¡4FõñVŒ])HþŒ‚ôÁ„&8Œ¥¬@1^  âg”£ f€í4êŽåY¢bcϨF Èý4jÍi$G~ÔXgÔ"Ù`{ŒÚ$á42¨Xò4êS¤1P<Ê”B®À4Tt°° €\Š>=ûSàQÉ Ô| Œ@Aù  81Ú?)~ù “8J| ¨à-hD-á„;kscope-1.9.4/core/images/struct.gif0000644000175000001440000000216611156714354016414 0ustar elahavusersGIF89aç¨ö« ö¬ö­ ö­÷­õ®ö®ö¯ö±ö±ö´ ö²÷²öµ ö³"÷³#ö´$ö´'÷´&÷µ)÷¶,ø¶*ø·,÷¸/÷¸1ö¹5÷¹4ö¾øº6÷º9÷»:ø»8÷»;÷¼=÷½>õÂø½>öÂ÷¿Gø¿EøÀHùÀGøÁJøÁLöÈ÷Ç'øÄTøÄVøÅVùÅVöÌöÌ÷ÇKùÆY÷Ì/ùÇ[øÉRùÉaùÉcùÉdúÊbøÊhøËiùËgùËiùÌløÍpùÎqùÎrùÎsøÔ<úÏrúÏsúÏtøÐzúÐuúÐvùÑxûÐ}øØFùÒøÕfúÓ€úÔ‚ùÔ…úÔƒúÔ„ùÖ}úÕ„øÛXúÖ‡úÖ‰øÚnùÙ…ûØùÞ`ûÙûÙ‘úÛ–ûÜ›ûÝ›üÝšûÝüÝœûÞŸüÞžûß›ûßûß©úà¤ûâ£ûâ¬üâªûâ­üâ¬ûã¯üã®üä¨ûæûçŸûåµúé“úé”ýå·üæ¶üæ¸ûêšûê›úé¨üç¶ûé§ýç¹üèºüè¼ýè»üè¾üé¾üê¼üêÂüëÄüëÅüëÆýëÅýìÇýìÉüíÈüíËýîÎýðÔþðÔýñÕýñ×ýôßýõäþöåþöçþ÷çþ÷éþøëþøìþùíþùîþùïþûõþü÷þýúþýûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù ÿ,þÿ H° ÁƒÿôÜ©C‡L._üƒ’¡8hÂ`alj€,E"$'#&=n¬ aã  KÉIfJ’*I`xÀ¢ ŸJ1á˜ys©'JsŠì<`ÁDŽúÀ9ƒç#%?¬xÒä€)€ó, g ˜O¨„ÔP"H¦â!ÐÎ8j¼LA…ªŠ "ìwƒ@7lÊx‘‚Ä*S…šd0@8®mÆx2D‡$¾|OÒPY€@1›è€£h¾ 6ý!<^ a!Ä>¥ø!|ù_”!9`¤èàƒÁ€¸D¡ÒBØð¿,9\˜øPa ‡PT!LW íhš´ .„P£ È;Їô¶`"ÕHѨK'æA- €\ x ‚•pP •E€ƒÍ €„(0 Dÿ̰Á…(°Á†–XP@;kscope-1.9.4/core/images/cancel.gif0000644000175000001440000000054611156714354016315 0ustar elahavusersGIF89a¥ÞÞÞß ß ßââ â!!ã''ã))å88éYYé\\ìmmìnnìssíttî}}òŸŸó¤¤õ¸¸õ¹¹÷ÅÅøÍÍùÓÓùÔÔúÝÝúÞÞýóóýôôýõõþûûÿÿÿÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞÞ!ù ?,ƒÀŸpH,ÈäÀl*‰Í¨S)­’Vë2«-6'!Œ€)À„&Óa”  A˜‘Pf…FžÏñé$¤vQ !! UM!!c€jR!!‰“M  ’œL!iœ!L!°œ\LX½WT\O¼¾ÄÇÈÄA;kscope-1.9.4/core/images/function.gif0000644000175000001440000000212711156714354016712 0ustar elahavusersGIF89açÆ Æ Æ! Æ! Æ" Æ# Ç# Ç%È%Ç&Ç'È,É/Ê0Ë3Ë4Ë4 Ë5 Ë6!Ë6"Ì6"Ë7#Í?,Î@-ÎA.ÎB0ÏC1ÏD2ÏE2ÐE2ÐG5ÐH6ÑM<ÓUDÔUDÔUEÔXGÕ]MÕ_NÖ`QÖaQØeV×fVØfWØgXÙhZÙiYÙm^ÛtfÛugÜvhÜviÜwiÜwjÝylÞ|oÞ~rß„wà‡zà‡{á‡{á‡|áˆ|ጀ⎃â„㔉䘎å˜å˜Žå™å™å›‘æ –æ —ç¦è¦žè¨Ÿè¨ é¨ é© é©¡éª¢êª¢é«£ìµ®ìµ¯ì¶¯í·°ì¸±í¹²í¹³íº³îº³í»³í»µî»´í¼µî¼µî½¶ðÅÀïÆ¿ðÇÂñÇÃñÊÄòÊÅñËÆòËÆòËÇñÌÇóÍÇóÐÌóÑÌóÓÎóÔÏõÛØöÛ×öÜØöÜÙöÝÙöÝÚ÷áß÷âß÷ãáøãà÷äáøæäùçåùèæúëéúìêúíêúíëüôóüõôüöõýøøþýýÿýüÿýýþþþÿÿÿÆ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ Æ !ù ÿ,þÿ H° Áƒÿšx1ã ’'tÒ‡Ð6a¨,9‚ãD‰b ²ÃæËCˆø$‚ñ¡ÁA1‹ÕY¦ £FGZàQA€‚Nɤ9N£C.Hx˜ €Ÿ÷𓆋+úÁ‚‚O¡þcˆŽ.QŒÄIÔ(ϘÂp*P 4[ ñ‘£Q£ â ;X 4Zž ñQˆ_œ~Zø_™ÄCzÐ`‘¤#&Ï +°Ê“"ˆ9>‰;?Š;@ŠCŒ>DŒ@EŒAFBGŽDHŽEIŽEHDIEIEK‘HM‘IM’IN“JP”LQ”MQ•MR•OT–PU–RU—RV—SV˜SX˜TX™TX™UZ™VZšV[šX\šX\›Y]›Y^›[^œZ^œ[_\`\`ž]až]až^bž_d `d ad¡af¡cg¡cf¢cg¢dh¢di¢eh£fi£fj£ej¤gk¤gl¥im¦jn§ko§lp§mp¨mq¨nq¨or¨ns©pu©qtªrvªsw¬ty¬uy¬vy­vz­w|®y}¯z~°{°}€±}²~ƒ³€„³„³‚ˆ¶…懋·ˆ‹·‰Œ¸Š¹‹˜À—œÂ™œÂšÂšŸÄ¡ÅŸ¢ÅŸ¥È£±Ï¯²Ï°²Ð±¹Ô·¼Õº¿Ø¾ÄÚÂÅÛÃÉÞÈÒãÑçðæèñçèñèêòêðõïóøóôøôõùõ÷ú÷ýýýÿÿÿm m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m !ù ÿ,þÿ H° ÁƒÿŽXñò¥‰”bGœ1Sˆèx!¢‚‰fí‘S¦J‘0Fpˆ ÀÁ3ƒøÌ9ƒI'b”ÀÐ@A4£-»Ú.Y*RŒôQâ‚ ;F)yšù°ë?ˆèxÁTßWF]*`—5Y8ZL„¨à`ODŠd ;â(øÆ@øÇB÷ÇE÷ÈGøÈHøÉJøÉLøÍJøÌVùÍWøÏRùÎ[÷ÐWøÏ`ùÐ_ùÐaùÑYùÐcùÒkúÓløÔnùÔoùÔqúÕrúÖtùÖwú×xúØzúÚ‚úÚ„ûÛ…úÛˆúÜŠûÜ‹ûÞ‘úߎûá™ûá›ûáûâ™ûâŸûâ¡üã ûäŸúåûä¥ûæœûå©ûæ©üç°üè²ûèµüé¶ûê±üë¸üëºüïÈýïËýðÉýñÍýó×üõÜþöâÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù ,š€‚ƒ„…†‡ˆ‰Š‹Œ…GQSE7(ŽHYWRI?6-!‹JZUPF=5+" ŠXVOD<4)! ‰CTNB;3*  ¹ˆLMA:2' ƈK@91,Ó¹ˆ>8/%ßà‡0.$éÔˆ#&òljúºEPÁ"úZ5: WdŽ"JœH1b ;kscope-1.9.4/core/images/include.gif0000644000175000001440000000050411156714354016505 0ustar elahavusersGIF89a¥+=€¶(p¨)q©*q©,s«,sª.u­/v­2x®2y®5{±8~´8~³9~³8}°<€µ<µ=¶@„¸?³C‡ºD‡»D‡ºD…¶GнG‹½KÀK¿Hˆ¸NÂNÁQ“ÄR“ÃT”Åh j¢k¢"n¥"n¤)s©0x¬7}¯>‚³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù?,aÀŸpH,ȤQÄd ›¢¢(„ŠF$J$ƒ‘ŒŠ%Aဖ)¦â‰pH(„ æ¤ê7(F) FZy *F‡!F¡¢£}¥¦§A;kscope-1.9.4/core/images/enumerator.gif0000644000175000001440000000111611156714354017243 0ustar elahavusersGIF89aÆQfSfSfTfThUiViVjWjXjYkYkZlZl[p^"sa&sb'tc(ud*ue*ve+vf,{k3}m5~n7~n9€o:p9€p:€q;€r<„t@†wE‡yFˆyG‰zH‰{I‰{J‹|K‹}KŒ~L’„V“…W“†Y“‡Y”‡Z•‡Z–ˆ[•‰\—Š_‘g‘hž’iž’jŸ“jŸ“k ”k¤˜r§œw§x¨x¨y©žz©Ÿ{ª {®¥ƒ±§…±¨‡²¨ˆ²©ˆ²©‰³ªŠ´ª‹´«‹½µ˜½µš¾¶š¿¶›Ä½£Ä¾¥ÈÁªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù ,«€‚ƒ„…†‡ˆ‰Š‹Œ…=AC9+Ž>NJD:2)! ‹>PKF;3*!ŠOLG=4*"«­ˆ?MH>5,#¹†BI?6-$¸È…E@7.%àÖ„<8/&ÓÆÕˆ10' ¸îLj ( Ó80‘† ¨Ý0š" ÞÃÇœ!\ÔÀM´ˆ¨Ú;G CŠ 2;kscope-1.9.4/core/process.cpp0000644000175000001440000000437711156714354015324 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "process.h" namespace KScope { namespace Core { Process::Process(QObject* parent) : QProcess(parent) { connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput())); connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(handleFinished(int, QProcess::ExitStatus))); connect(this, SIGNAL(error(QProcess::ProcessError)), this, SLOT(handleError(QProcess::ProcessError))); connect(this, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(handleStateChange(QProcess::ProcessState))); } Process::~Process() { } void Process::setDeleteOnExit() { deleteOnExit_ = true; } void Process::readStandardOutput() { // Read from standard output. stdOut_ += readAllStandardOutput(); // Parse the text. if (!parse(stdOut_)) { emit parseError(); return; } } void Process::readStandardError() { qDebug() << readAllStandardError(); } void Process::handleFinished(int code, QProcess::ExitStatus status) { qDebug() << "Process finished" << code << status; } void Process::handleError(QProcess::ProcessError code) { qDebug() << "Process error" << code; } void Process::handleStateChange(QProcess::ProcessState state) { qDebug() << "Process state" << state; if (state == QProcess::NotRunning && deleteOnExit_) deleteLater(); } } } kscope-1.9.4/core/exception.h0000644000175000001440000000350611156714354015302 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_EXCEPTION_H__ #define __CORE_EXCEPTION_H__ #include #include namespace KScope { namespace Core { /** * A simple exception object. * Provides a text explaining the cause of the exception. * @author Elad Lahav */ class Exception { public: /** * Class constructor. * @param reason Describes the cause of the exception */ Exception(const QString& reason) : reason_(reason) {} /** * @return Text describing the cause of the exception */ const QString& reason() const { return reason_; } /** * Shows a message box explaining the exception. */ void showMessage() const { QMessageBox::critical(0, QObject::tr("Exception"), reason_); } private: /** * The cause of the exception, as passed to the constructor. */ QString reason_; }; } // namespace Core } // namespace KScope #endif // __CORE_EXCEPTION_H__ kscope-1.9.4/core/codebase.h0000644000175000001440000000426711156714354015056 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_CODEBASE_H__ #define __CORE_CODEBASE_H__ #include #include "globals.h" namespace KScope { namespace Core { /** * An abstract base class representing a set of source files. * KScope describes a project as a set of source files and a data engine that * indexes these files and can be queried for cross-reference information. * While the engine can potentially be responsible for managing the code base, * this is not always the case: Cscope can hold the list of files to work on in * a cscope.files file that is separate from the corss-reference database. * This class adds flexibility by allowing separate management of the set of * source files and their index. * @author Elad Lahav */ class Codebase : public QObject { Q_OBJECT public: Codebase(QObject* parent = 0) : QObject(parent) {} ~Codebase() {} virtual void open(const QString& initString, Callback<>* cb) = 0; virtual void save(const QString& initString) = 0; virtual void getFiles(Callback& cb) const = 0; virtual void setFiles(const QStringList& fileList) = 0; virtual bool canModify() = 0; virtual bool needFiles() { return false; } signals: void loaded(); void modified(); }; } } #endif // __CORE_CODEBASE_H__ kscope-1.9.4/core/images.h0000644000175000001440000000434011156714354014546 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_IMAGES_H__ #define __CORE_IMAGES_H__ #include #include "globals.h" namespace KScope { namespace Core { /** * Provides images for various values. * @author Elad Lahav */ struct Images { /** * Generates an icon for a given tag type. * TODO This should probably be moved somewhere else (like an Images class) * @param type The type for which an icon is requested * @return The matching icon */ static QIcon tagIcon(Tag::Type type) { switch (type) { case Tag::UnknownTag: return QIcon(); case Tag::Variable: return QIcon(":/images/variable"); case Tag::Function: return QIcon(":/images/function"); case Tag::Struct: return QIcon(":/images/struct"); case Tag::Union: return QIcon(":/images/union"); case Tag::Member: return QIcon(":/images/member"); case Tag::Enum: return QIcon(":/images/enum"); case Tag::Enumerator: return QIcon(":/images/enumerator"); case Tag::Typedef: return QIcon(":/images/typedef"); case Tag::Define: return QIcon(":/images/define"); case Tag::Include: return QIcon(":/images/include"); case Tag::Label: return QIcon(":/images/label"); default: Q_ASSERT(false); } return QIcon(); } }; } } // namespace KScope #endif // __CORE_IMAGES_H__ kscope-1.9.4/core/locationlistmodel.cpp0000644000175000001440000001542111156714354017363 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "locationlistmodel.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent Parent object */ LocationListModel::LocationListModel(QObject* parent) : LocationModel(parent), locationsAdded_(false) { } /** * Class destructor. */ LocationListModel::~LocationListModel() { } /** * Appends the given list to the one held by the model. * @param locList Result information * @param parent Index under which to add the results (ignored) */ void LocationListModel::add(const LocationList& locList, const QModelIndex& parent) { (void)parent; locationsAdded_ = true; // Determine the first and last rows for the new items. int firstRow = locList_.size(); int lastRow = firstRow + locList.size() - 1; if (lastRow < firstRow) return; // Begin row insertion. // This is required by QAbstractItemModel. beginInsertRows(QModelIndex(), firstRow, lastRow); // Add the entries. // The condition optimises for the case where the list can be internally // copied from one object to another. // Not sure whether the condition is also checked by the += operator itself // (probably it is, but let's be on the safe side). if (locList_.isEmpty()) locList_ = locList; else locList_ += locList; // End row insertion. // This is required by QAbstractItemModel. endInsertRows(); } /** * Determines whether the index has children, and if not, for what reason. * @param index The index to check * @return See LocationModel::IsEmptyResult */ LocationModel::IsEmptyResult LocationListModel::isEmpty(const QModelIndex& index) const { if (index.isValid() || !locationsAdded_) return Unknown; return locList_.isEmpty() ? Empty : Full; } /** * Removes all descriptors from the lists. * Resets the model. * @param parent ignored */ void LocationListModel::clear(const QModelIndex& parent) { (void)parent; if (locList_.isEmpty()) return; locList_.clear(); locationsAdded_ = false; reset(); } /** * Converts an index into a location descriptor. * @param idx The index to convert * @param loc An object to fill with the location information * @return true if successful, false if the index does not describe a valid * position in the location list */ bool LocationListModel::locationFromIndex(const QModelIndex& idx, Location& loc) const { // Make sure the index is valid. if (!idx.isValid()) return false; // Make sure the index is inside the list's boundaries. int pos = idx.row(); if (pos < 0 || pos >= locList_.size()) return false; // Copy the location descriptor. loc = locList_.at(pos); return true; } /** * Returns the location at the first position in the list. * @param loc An object to fill with the location information * @return true if successful, false if the list is empty */ bool LocationListModel::firstLocation(Location& loc) const { if (locList_.isEmpty()) return false; loc = locList_.at(0); return true; } /** * Finds the successor of the given index. * In a list, this is simply the next item. * @param idx The index for which to find a successor * @return The successor index */ QModelIndex LocationListModel::nextIndex(const QModelIndex& idx) const { // If the given index is invalid, return the index of the first item on the // list. if (!idx.isValid()) return index(0, 0, QModelIndex()); // Do not go past the last item. if (idx.row() >= (rowCount() - 1)) return QModelIndex(); // Return the index of the next item. return index(idx.row() + 1, 0, idx.parent()); } /** * Finds the predecessor of the given index. * In a list, this is simply the previous item. * @param idx The index for which to find a predecessor * @return The predecessor index */ QModelIndex LocationListModel::prevIndex(const QModelIndex& idx) const { // If the given index is invalid, return the index of the last item on the // list. if (!idx.isValid()) return index(rowCount() - 1, 0, QModelIndex()); // Do not go before the first item. if (idx.row() <= 0) return QModelIndex(); // Return the index of the next item. return index(idx.row() - 1, 0, idx.parent()); } /** * Creates an index for the given parameters. * @param row Row number, with respect to the parent * @param column Column number * @param parent Parent index * @return The new index, if created, an invalid index otherwise */ QModelIndex LocationListModel::index(int row, int column, const QModelIndex& parent) const { if (parent.isValid()) return QModelIndex(); if (row < 0 || row >= locList_.size()) return QModelIndex(); return createIndex(row, column); } /** * Returns an index for the parent of the given one. * Since this is a flat list, there are no parent indices, so an invalid index * is always returned. * @param idx The index for which the parent is to be returned * @return An invalid index */ QModelIndex LocationListModel::parent(const QModelIndex& idx) const { (void)idx; return QModelIndex(); } /** * Determines the number of children for the given parent index. * For a flat list, this is the number of items for the root (invalid) index, * and 0 for any other index. * @param parent The parent index * @return The number of child indices belonging to the parent */ int LocationListModel::rowCount(const QModelIndex& parent) const { if (!parent.isValid()) return locList_.size(); return 0; } /** * Extracts location data from the given index. * @param index The index for which data is requested * @param role The role of the data * @return */ QVariant LocationListModel::data(const QModelIndex& idx, int role) const { // No data for invalid indices. if (!idx.isValid()) return QVariant(); // Get the column-specific data. return locationData(locList_.at(idx.row()), idx.column(), role); } } // namespace Core } // namespace KScope kscope-1.9.4/core/codebasemodel.h0000644000175000001440000000506711156714354016076 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_CODEBASEMODEL_H #define __CORE_CODEBASEMODEL_H #include #include "treeitem.h" #include "codebase.h" namespace KScope { namespace Core { /** * @author Elad Lahav */ class CodebaseModel : public QAbstractItemModel { Q_OBJECT public: CodebaseModel(const Codebase*, const QString& rootPath = "/", QObject* parent = 0); ~CodebaseModel(); void addFiles(const QStringList&); void getFiles(QStringList&) const; virtual QModelIndex index(int row, int column, const QModelIndex& parent) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const; virtual QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const; private: typedef TreeItem ItemT; ItemT root_; void addFile(const QString&); void getFiles(const ItemT*, const QString&, QStringList&) const; static inline ItemT* indexData(QModelIndex index) { return static_cast(index.internalPointer()); } struct AddFilesCallback : public Core::Callback { CodebaseModel* model_; AddFilesCallback(CodebaseModel* model) : model_(model) {} void call(const QString& file) { model_->addFile(file); } }; friend struct AddFilesCallback; #ifndef QT_NO_DEBUG void verify(const QModelIndex&); #endif }; } } #endif // __CORE_CODEBASEMODEL_H kscope-1.9.4/core/locationtreemodel.cpp0000644000175000001440000002307611156714354017354 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "locationtreemodel.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent Parent object */ LocationTreeModel::LocationTreeModel(QObject* parent) : LocationModel(parent), root_(Location()) { } /** * Class destructor. */ LocationTreeModel::~LocationTreeModel() { } /** * Appends the given list to the one held by the model. * @param locList Result information * @param parent Index under which to add the results */ void LocationTreeModel::add(const LocationList& locList, const QModelIndex& parent) { Node* node; // Determine the node under which to add the results. if (!parent.isValid()) { node = &root_; } else { node = static_cast(parent.internalPointer()); if (node == NULL) return; } // Mark the item for use with isEmpty(). // TODO: Is there a way to force the view to repaint this item? node->data().locationsAdded_ = true; // Determine the first and last rows for the new items. int firstRow = node->childCount(); int lastRow = firstRow + locList.size() - 1; if (lastRow < firstRow) return; // Begin row insertion. // This is required by QAbstractItemModel. beginInsertRows(parent, firstRow, lastRow); // Add the entries. foreach (Location loc, locList) node->addChild(loc); // End row insertion. // This is required by QAbstractItemModel. endInsertRows(); } /** * Determines whether the index has children, and if not, for what reason. * @param index The index to check * @return See LocationModel::IsEmptyResult */ LocationModel::IsEmptyResult LocationTreeModel::isEmpty(const QModelIndex& index) const { const Node* node; // Get the node from the index. if (!index.isValid()) { node = &root_; } else { node = static_cast(index.internalPointer()); if (node == NULL) return Unknown; } // Return Unknown if locations were never added under this item. if (!node->data().locationsAdded_) return Unknown; // Return Empty or Full, based on the existence of children. return node->childCount() == 0 ? Empty : Full; } /** * Removes all tree nodes rooted at the given index. * @param parent The index to start from */ void LocationTreeModel::clear(const QModelIndex& parent) { // Handle the root node (removing all data from the model). if (!parent.isValid()) { if (root_.childCount() > 0) { root_.clear(); root_.data().locationsAdded_ = false; reset(); } return; } // Get the node from the index. Node* node = static_cast(parent.internalPointer()); if (node == NULL || node->childCount() == 0) return; // Delete all descendants. beginRemoveRows(parent, 0, node->childCount() - 1); node->clear(); node->data().locationsAdded_ = false; endRemoveRows(); } /** * Converts an index into a location descriptor. * @param idx The index to convert * @param loc An object to fill with the location information * @return true if successful, false if the index does not describe a valid * position in the location tree */ bool LocationTreeModel::locationFromIndex(const QModelIndex& idx, Location& loc) const { // Make sure the index is valid. if (!idx.isValid()) return false; Node* node = static_cast(idx.internalPointer()); if (node == NULL) return false; loc = node->data().loc_; return true; } /** * Returns the location at the root of the tree. * @param loc An object to fill with the location information * @return true if successful, false if the list is empty */ bool LocationTreeModel::firstLocation(Location& loc) const { if (root_.childCount() == 0) return false; loc = root_.child(0)->data().loc_; return true; } /** * Finds the successor of the given index. * @param idx The index for which to find a successor * @return The successor index */ QModelIndex LocationTreeModel::nextIndex(const QModelIndex& idx) const { // If the given index is invalid, return the index of the first item on the // list. if (!idx.isValid()) return index(0, 0, QModelIndex()); // Get the tree item for the index. const Node* node = static_cast(idx.internalPointer()); if (node == NULL) return QModelIndex(); // Go up the tree, looking for the first immediate sibling. const Node* parent; while ((parent = node->parent()) != NULL) { // Get the node's sibling. node = parent->child(node->index() + 1); if (node != NULL) return createIndex(node->index(), 0, (void*)node); node = parent; } return QModelIndex(); } /** * Finds the predecessor of the given index. * @param idx The index for which to find a predecessor * @return The predecessor index */ QModelIndex LocationTreeModel::prevIndex(const QModelIndex& idx) const { // If the given index is invalid, return the index of the first item on the // list. // TODO: What's the best default for a previous index on an invalid index? if (!idx.isValid()) return index(0, 0, QModelIndex()); // Get the tree item for the index. const Node* node = static_cast(idx.internalPointer()); if (node == NULL) return QModelIndex(); // Go up the tree, looking for the first immediate sibling. const Node* parent; while ((parent = node->parent()) != NULL) { // Get the node's sibling. node = parent->child(node->index() - 1); if (node != NULL) return createIndex(node->index(), 0, (void*)node); node = parent; } return QModelIndex(); } /** * Creates an index for the given parameters. * @param row Row number, with respect to the parent * @param column Column number * @param parent Parent index * @return The new index, if created, an invalid index otherwise */ QModelIndex LocationTreeModel::index(int row, int column, const QModelIndex& parent) const { // Extract the node object from the index. const Node* node; if (!parent.isValid()) { node = &root_; } else { // Get the tree item for the parent. node = static_cast(parent.internalPointer()); if (node == NULL) return QModelIndex(); } // Get the child at the row'th position. node = node->child(row); if (node == NULL) return QModelIndex(); return createIndex(row, column, (void*)node); } /** * Returns an index for the parent of the given one. * @param idx The index for which the parent is to be returned * @return An invalid index */ QModelIndex LocationTreeModel::parent(const QModelIndex& idx) const { if (!idx.isValid()) return QModelIndex(); // Get the tree item for the index. const Node* node = static_cast(idx.internalPointer()); if (node == NULL) return QModelIndex(); // Get the parent node. node = node->parent(); if ((node == NULL) || (node == &root_)) return QModelIndex(); return createIndex(node->index(), 0, (void*)node); } /** * Determines the number of children for the given parent index. * @param parent The parent index * @return The number of child indices belonging to the parent */ int LocationTreeModel::rowCount(const QModelIndex& parent) const { const Node* node; if (!parent.isValid()) { // An invalid index represents the root item. node = &root_; } else { // Get the tree item for the index. node = static_cast(parent.internalPointer()); if (node == NULL) return 0; } return node->childCount(); } /** * Determines whether the node at the given index has children. * We return true if one of two conditions are met: * 1. The node has children * 2. The node represents a function that was not yet queried * Case (2) will include an expansion symbol next to the function, which, when * clicked, will result in a query for called/calling functions. * @param parent The parent index * @return true if the parent has children (or can have children), false * otherwise */ bool LocationTreeModel::hasChildren(const QModelIndex& parent) const { const Node* node; if (!parent.isValid()) { // An invalid index represents the root item. node = &root_; } else { // Get the tree item for the index. node = static_cast(parent.internalPointer()); if (node == NULL) return 0; } return node->childCount() > 0; } /** * Extracts location data from the given index. * @param index The index for which data is requested * @param role The role of the data * @return */ QVariant LocationTreeModel::data(const QModelIndex& idx, int role) const { // No data for invalid indices. if (!idx.isValid()) { if (idx.column() == 0) return ""; return QVariant(); } // Get the location for the index's row. Node* node = static_cast(idx.internalPointer()); if (node == NULL) return false; // Get the column-specific data. return locationData(node->data().loc_, idx.column(), role); } } // namespace Core } // namespace KScope kscope-1.9.4/core/locationmodel.h0000644000175000001440000001153011156714354016131 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_LOCATIONMODEL_H__ #define __CORE_LOCATIONMODEL_H__ #include #include "globals.h" namespace KScope { namespace Core { /** * Abstract base-class for location models. * Provides a common base for LocationListModel and LocationTreeModel. * @author Elad Lahav */ class LocationModel : public QAbstractItemModel { Q_OBJECT public: LocationModel(QObject* parent = 0); virtual ~LocationModel(); void setRootPath(const QString&); /** * Determines which fields of a location structure the model supports, and * in what order. * @param colList An ordered list of location structure fields */ void setColumns(const QList& colList) { colList_ = colList; reset(); } /** * @return The list of query fields presented by the model as columns */ const QList& columns() const { return colList_; } /** * Adds a list of locations under the given index * @param list The list of locations * @param parent The index under which locations should be added */ virtual void add(const LocationList& list, const QModelIndex& parent) = 0; /** * Possible return values for the isEmpty() method. */ enum IsEmptyResult { /** add() was called on this index, but no children were created. */ Empty, /** add() was called on this index and it has children. */ Full, /** add() was not called on this index. */ Unknown }; /** * Determines whether the given index has children, and if not, whether this * is because add() was called with no locations or add() was never called * for this index. * This method is useful for distinguishing queried-but-empty indices from * non-queried ones in a lazy-query view. * @param index The required index * @return See IsEmptyResult */ virtual IsEmptyResult isEmpty(const QModelIndex& index) const = 0; /** * Deletes all locations in the model rooted at the given index. */ virtual void clear(const QModelIndex& parent) = 0; /** * Converts a model index into a location structure. * @param index The index to convert * @param loc The structure to fill * @return true if the index represents a valid location, false otherwise */ virtual bool locationFromIndex(const QModelIndex& index, Location& loc) const = 0; /** * Fills a location structure with the information stored in the first * index. * @param loc The structure to fill * @return true if a valid index was located, false otherwise */ virtual bool firstLocation(Location& loc) const = 0; /** * Finds the next index in the model. * The definition of "next" is implementation-dependent. * @param index The index to start the search from * @return The next index in the model */ virtual QModelIndex nextIndex(const QModelIndex& index) const = 0; /** * Finds the previous index in the model. * The definition of "previous" is implementation-dependent. * @param index The index to start the search from * @return The previous index in the model */ virtual QModelIndex prevIndex(const QModelIndex& index) const = 0; // QAsbstractItemModel implementation. virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; virtual QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const; #ifndef QT_NO_DEBUG void verify(const QModelIndex& parentIndex = QModelIndex()) const; #endif protected: /** * The list of query fields presented by the model as columns. */ QList colList_; /** * A common root path for all files in the model. * Files for which this path is a prefix will be presented with a '$' sign * as an abbreviation of the common path. */ QString rootPath_; QVariant locationData(const Location&, uint, int) const; QString columnText(Location::Fields) const; }; } // namespace Core } // namespace KScope #endif // __CORE_LOCATIONMODEL_H__ kscope-1.9.4/core/globals.h0000644000175000001440000001362311156714354014730 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_GLOBALS_H__ #define __CORE_GLOBALS_H__ #include namespace KScope { namespace Core { /** * The Tag structure provides information for a defined symbol in the code base. */ struct Tag { enum Type { /** Default tag. */ UnknownTag, /** Variable declaration. */ Variable, /** Function declaration/definition. */ Function, /** Structure. */ Struct, /** Union. */ Union, /** Structure/union field. */ Member, /** Enumeration declaration. */ Enum, /** Member in an enumeration. */ Enumerator, /** Type definition. */ Typedef, /** Preprocessor definition. */ Define, /** Preprocessor #include directive. */ Include, /** Goto label. */ Label }; /** * The name of the tag. */ QString name_; /** * The tag's type, determined by its definition. */ Type type_; /** * Some tags are defined within a scope (e.g., a structure member). * An empty string is used for the "Global" scope. */ QString scope_; /** * Default constructor. * Creates an empty (invalid) tag. */ Tag() : type_(UnknownTag) {} }; /** * A location in the code base. * Locations are at the heart of the browsing system offered by KScope. * Query results, navigation history and bookmarks are all expressed as * lists of Location objects. * A location refers to a line and column in a file. Optionally, it may * reference a specific tag, in which case its type and scope can also be * given. */ struct Location { /** * File path. */ QString file_; /** * Line number. */ uint line_; /** * Column number. */ uint column_; /** * Tag information (optional). */ Tag tag_; /** * Line text. */ QString text_; /** * Each member in the structure is assigned a numeric value. These can be * used for, e.g., creating lists of fields for displaying query results. */ enum Fields { /** File path. */ File, /** Line number. */ Line, /** Column number. */ Column, /** Symbol name. */ TagName, /** Tag type (function, variable, structure, etc.) */ TagType, /** Scope of the tag (function name, structure, global, etc.) */ Scope, /** Line text. */ Text }; /** * Default constructor. * Creates an empty (invalid) location object. */ Location() : line_(0), column_(0) {} /** * Convenience constructor. * @param file * @param line * @param column */ Location(const QString& file, uint line = 0, uint column = 0) : file_(file), line_(line), column_(column) {} /** * @return true if the object represents a valid location (at least the * file path is set), false otherwise */ bool isValid() const { return !file_.isEmpty(); } /** * Two locations are equal if and only if they refer to the same line and * column in the same file. * @param other The location to compare with * @return true if the locations are equal, false otherwise */ bool operator==(const Location& other) { return ((file_ == other.file_) && (line_ == other.line_) && (column_ == other.column_)); } }; /** * A list of locations. * This is useful for passing query results around. */ typedef QList LocationList; /** * Defines parameters for running queries on an engine. */ struct Query { /** * Possible queries. */ enum Type { /** Default type. */ Invalid, /** Free text search. */ Text, /** Symbol definition */ Definition, /** All references to a symbol */ References, /** Functions called by the given function name */ CalledFunctions, /** Functions calling the given function name */ CallingFunctions, /** Search for a file name */ FindFile, /** Search for files including a given file name */ IncludingFiles, /** List all tags in the given file */ LocalTags }; /** * The query type. */ Type type_; /** * Determines certain aspects of the query. */ enum Flags { /** * Make the search case-insensitive. */ IgnoreCase = 0x1, /** * The pattern is a regular expression. */ RegExp = 0x2 }; /** * The pattern to search for. */ QString pattern_; /** * Modifiers: A bitmask of Flags. */ uint flags_; /** * Default constructor. * Creates an invalid query object. */ Query() : type_(Invalid) {} /** * Struct constructor. * @param type The type of query * @param pattern The pattern to look for * @param flags Modifiers */ Query(Type type, const QString& pattern, uint flags = 0) : type_(type), pattern_(pattern), flags_(flags) {} }; /** * A generic associative set, indexed by strings. */ typedef QMap KeyValuePairs; /** * Used as a default type. */ struct Void {}; /** * Defines a generic callback functor, with a type T parameter. */ template struct Callback { virtual void call(T t) = 0; }; /** * Defines a generic callback functor, without parameters. */ template<> struct Callback { virtual void call() = 0; }; } // namespace Core } // namespace KScope #endif // __CORE_GLOBALS_H__ kscope-1.9.4/core/locationview.cpp0000644000175000001440000003056711156714354016351 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "locationview.h" #include "locationlistmodel.h" #include "locationtreemodel.h" #include "textfilterdialog.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent The parent widget * @param type Whether the view works in list or tree modes */ LocationView::LocationView(QWidget* parent, Type type) : QTreeView(parent), type_(type) { // Set tree view properties. setRootIsDecorated(type_ == Tree); setUniformRowHeights(true); setExpandsOnDoubleClick(false); // Create the model proxy. LocationViewProxyModel* proxy = new LocationViewProxyModel(this); setModel(proxy); // Create a location model. switch (type_) { case List: proxy->setSourceModel(new LocationListModel(this)); break; case Tree: proxy->setSourceModel(new LocationTreeModel(this)); break; } // Emit requests for locations when an item is double-clicked. connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(requestLocation(const QModelIndex&))); // Create the context menu. menu_ = new QMenu(this); menu_->addAction(tr("&Filter..."), this, SLOT(promptFilter())); menu_->addAction(tr("C&lear filter"), this, SLOT(clearFilter())); } /** * Class destructor. */ LocationView::~LocationView() { } /** * Adjusts all columns to fit the their contents. */ void LocationView::resizeColumns() { for (int i = 0; i < locationModel()->columnCount(); i++) resizeColumnToContents(i); } /** * Creates an XML representation of the view, which can be used for storing the * model's data in a file. * @param doc The XML document object to use * @param viewElem The element representing the view */ void LocationView::toXML(QDomDocument& doc, QDomElement& viewElem) const { // Create an element for storing the view. viewElem.setAttribute("name", windowTitle()); viewElem.setAttribute("type", QString::number(type_)); // Create a "Columns" element. QDomElement colsElem = doc.createElement("Columns"); viewElem.appendChild(colsElem); // Add an element for each column. foreach (Location::Fields field, locationModel()->columns()) { QDomElement colElem = doc.createElement("Column"); colElem.setAttribute("field", QString::number(field)); colsElem.appendChild(colElem); } // Add locations. locationToXML(doc, viewElem, QModelIndex()); } /** * Loads a query view from an XML representation. * @param root The root element for the query's XML representation */ void LocationView::fromXML(const QDomElement& viewElem) { // Reset the model. locationModel()->clear(QModelIndex()); // TODO: Is there a guarantee of order? QDomNodeList columnNodes = viewElem.elementsByTagName("Column"); QList colList; for (int i = 0; i < columnNodes.size(); i++) { QDomElement elem = columnNodes.at(i).toElement(); if (elem.isNull()) continue; colList.append(static_cast (elem.attribute("field").toUInt())); } locationModel()->setColumns(colList); // Find the element that is a child of the root element. QDomNodeList childNodes = viewElem.childNodes(); for (int i = 0; i < childNodes.size(); i++) { QDomElement elem = childNodes.at(i).toElement(); if (elem.isNull() || elem.tagName() != "LocationList") continue; // Load locations. locationFromXML(elem, QModelIndex()); } #ifndef QT_NO_DEBUG locationModel()->verify(); #endif } /** * Selects the next available index in the proxy. */ void LocationView::selectNext() { QModelIndex index = moveCursor(MoveNext, 0); if (!index.isValid()) return; setCurrentIndex(index); Location loc; if (locationModel()->locationFromIndex(proxy()->mapToSource(index), loc)) emit locationRequested(loc); } /** * Selects the previous available index in the proxy. */ void LocationView::selectPrev() { QModelIndex index = moveCursor(MovePrevious, 0); if (!index.isValid()) return; setCurrentIndex(index); Location loc; if (locationModel()->locationFromIndex(proxy()->mapToSource(index), loc)) emit locationRequested(loc); } /** * Displays the context menu in response to the matching event. * @param event Event parameters */ void LocationView::contextMenuEvent(QContextMenuEvent* event) { menu_->popup(event->globalPos()); menuIndex_ = indexAt(event->pos()); event->accept(); } /** * Recursively transforms the location hierarchy stored in the model to an XML * sub-tree. * The XML representation of locations is composed of a element * holding a list of elements. For a tree model, elements * may in turn hold a sub-element, and so on. * @param doc The XML document object to use * @param parentElem XML element under which new location elements should be * created * @param index The source index to store (along with its children) */ void LocationView::locationToXML(QDomDocument& doc, QDomElement& parentElem, const QModelIndex& index) const { QDomElement elem; if (index.isValid()) { // A non-root index. // Translate the index into a location information structure. Location loc; if (!locationModel()->locationFromIndex(index, loc)) return; // Create an XML element for the location. elem = doc.createElement("Location"); parentElem.appendChild(elem); // Add a text node for each structure member. const QList& colList = locationModel()->columns(); foreach (Location::Fields field, colList) { QString name; QDomNode node; switch (field) { case Location::File: name = "File"; node = doc.createTextNode(loc.file_); break; case Location::Line: name = "Line"; node = doc.createTextNode(QString::number(loc.line_)); break; case Location::Column: name = "Column"; node = doc.createTextNode(QString::number(loc.column_)); break; case Location::TagName: name = "TagName"; node = doc.createTextNode(loc.tag_.name_); break; case Location::TagType: name = "TagType"; node = doc.createTextNode(QString::number(loc.tag_.type_)); break; case Location::Scope: name = "Scope"; node = doc.createTextNode(loc.tag_.scope_); break; case Location::Text: name = "Text"; node = doc.createCDATASection(loc.text_); break; } QDomElement child = doc.createElement(name); child.appendChild(node); elem.appendChild(child); } } else { // For the root index, use the given parent element as the parent of // the location list created by top-level items. elem = parentElem; } // Create an element list using the index's children. // A element is created for queried items (whether there // were any results or not). An element is not created for non-queried // items, so that locationFromXML() does not call add() for such items, // correctly restoring their status. if (locationModel()->isEmpty(index) != LocationModel::Unknown) { // Create the element. QDomElement locListElem = doc.createElement("LocationList"); QModelIndex proxyIndex = proxy()->mapFromSource(index); locListElem.setAttribute("expanded", isExpanded(proxyIndex) ? "1" : "0"); elem.appendChild(locListElem); // Add child locations. for (int i = 0; i < locationModel()->rowCount(index); i++) locationToXML(doc, locListElem, locationModel()->index(i, 0, index)); } } /** * Loads a hierarchy of locations from an XML document into the model. * See locationToXML() for the XML format. * @param locListElem A XML element * @param parentIndex The source model index under which locations should be * added */ void LocationView::locationFromXML(const QDomElement& locListElem, const QModelIndex& parentIndex) { // Get a list of location elements. QDomNodeList nodes = locListElem.childNodes(); // Translate elements into a list of location objects. // The list is used to store sub-lists encountered inside the location // element. These will be loaded later. It's better to first construct the // list of locations for the current level, rather than follow the XML // tree depth-first, due to the behaviour of the add() method. LocationList locList; QList< QPair > childLists; for (int i = 0; i < nodes.size(); i++) { // Get the current location element. QDomElement elem = nodes.at(i).toElement(); if (elem.isNull() || elem.tagName() != "Location") continue; // Iterate over the sub-elements, which represent either location // properties, or nested location lists. We expect at most one of the // latter. Location loc; QDomNodeList childNodes = elem.childNodes(); for (int j = 0; j < childNodes.size(); j++) { // Has to be an element. QDomElement child = childNodes.at(j).toElement(); if (child.isNull()) continue; // Extract location data from the element. if (child.tagName() == "File") loc.file_ = child.text(); else if (child.tagName() == "Line") loc.line_ = child.text().toUInt(); else if (child.tagName() == "Column") loc.column_ = child.text().toUInt(); else if (child.tagName() == "TagName") loc.tag_.name_ = child.text(); else if (child.tagName() == "TagType") loc.tag_.type_ = static_cast(child.text().toUInt()); else if (child.tagName() == "Scope") loc.tag_.scope_ = child.text(); else if (child.tagName() == "Text") loc.text_ = child.firstChild().toCDATASection().data(); else if (child.tagName() == "LocationList") childLists.append(QPair(i, child)); } // Add to the location list. locList.append(loc); } // Store locations in the model. locationModel()->add(locList, parentIndex); // Load any sub-lists encountered earlier. QList< QPair >::Iterator itr; for (itr = childLists.begin(); itr != childLists.end(); ++itr) { locationFromXML((*itr).second, locationModel()->index((*itr).first, 0, parentIndex)); } // Expand the item if required. if (locListElem.attribute("expanded").toUInt()) expand(proxy()->mapFromSource(parentIndex)); } /** * Called when the user double-clicks a location item in the list. * Emits the locationRequested() signal for this location. * @param index The clicked item (proxy index) */ void LocationView::requestLocation(const QModelIndex& index) { Location loc; if (locationModel()->locationFromIndex(proxy()->mapToSource(index), loc)) emit locationRequested(loc); } /** * Displays the text filter dialogue. * If a filter is specified by the user, it is applied to the proxy model. */ void LocationView::promptFilter() { // Create the dialogue. TextFilterDialog dlg(proxy()->filterRegExp()); // Populate the "Filter By" list. KeyValuePairs pairs; for (int i = 0; i < locationModel()->columnCount(); i++) { QString colName = locationModel()->headerData(i, Qt::Horizontal, Qt::DisplayRole) .toString(); pairs[colName] = i; } dlg.setFilterByList(pairs); dlg.setFilterByValue(menuIndex_.column()); // Show the dialogue. if (dlg.exec() != QDialog::Accepted) return; // Apply the filter. proxy()->setFilterKeyColumn(dlg.filterByValue().toInt()); QRegExp filter = dlg.filter(); proxy()->setFilterRegExp(filter); emit isFiltered(filter.isEmpty()); } /** * Removes any filters from the proxy. */ void LocationView::clearFilter() { proxy()->setFilterRegExp(QRegExp()); emit isFiltered(false); } } // namespace Core } // namespace KScope kscope-1.9.4/core/locationtreemodel.h0000644000175000001440000000553411156714354017020 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_LOCATIONTREEMODEL_H__ #define __CORE_LOCATIONTREEMODEL_H__ #include "locationmodel.h" #include "treeitem.h" namespace KScope { namespace Core { /** * A tree-like model for holding location results. * This is suitable for creating call/calling trees. For flat result lists, use * the more efficient LocationListModel. * @author Elad Lahav */ class LocationTreeModel : public LocationModel { Q_OBJECT public: LocationTreeModel(QObject* parent = 0); ~LocationTreeModel(); // LocationModel implementation. void add(const LocationList&, const QModelIndex&); IsEmptyResult isEmpty(const QModelIndex&) const; void clear(const QModelIndex&); bool locationFromIndex(const QModelIndex&, Location&) const; bool firstLocation(Location&) const; QModelIndex nextIndex(const QModelIndex&) const; QModelIndex prevIndex(const QModelIndex&) const; // QAsbstractItemModel implementation. virtual QModelIndex index(int row, int column, const QModelIndex& parent) const; virtual QModelIndex parent(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const; virtual QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const; private: /** * Data stored in a single node in the tree. */ struct LocationTreeItem { /** * Location information. */ Location loc_; /** * Whether add() was called on index for this item. * Required by isEmpty(). */ bool locationsAdded_; /** * Struct constructor. * @param loc The location to store */ LocationTreeItem(const Location& loc) : loc_(loc), locationsAdded_(false) {} }; typedef TreeItem Node; /** * The root item of the tree. */ Node root_; }; } // namespace Core } // namespace KScope #endif // __CORE_LOCATIONTREEMODEL_H__ kscope-1.9.4/core/strings.h0000644000175000001440000000437711156714354015004 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_STRINGS_H__ #define __CORE_STRINGS_H__ #include "globals.h" namespace KScope { namespace Core { /** * Translates various values into strings. * This class inherits from QObject in order to have access to the tr() method. * @author Elad Lahav */ struct Strings : public QObject { /** * Generates an icon for a given tag type. * TODO This should probably be moved somewhere else (like a Strings class) * @param type The type for which a name is requested * @return The matching name */ static QString tagName(Tag::Type type) { switch (type) { case Tag::UnknownTag: return QString(); case Tag::Variable: return tr("Variable"); case Tag::Function: return tr("Function"); case Tag::Struct: return tr("Struct"); case Tag::Union: return tr("Union"); case Tag::Member: return tr("Struct/Union Member"); case Tag::Enum: return tr("Enumeration"); case Tag::Enumerator: return tr("Enumeration Value"); case Tag::Typedef: return tr("Type Definition"); case Tag::Define: return tr("Preprorcessor Definition"); case Tag::Include: return tr("#include Directive"); case Tag::Label: return tr("Go-to Label"); default: Q_ASSERT(false); } return QString(); } }; } } // namespace KScope #endif // __CORE_STRINGS_H__ kscope-1.9.4/core/process.h0000644000175000001440000000326111156714354014760 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_PROCESS_H #define __CORE_PROCESS_H #include #include "statemachine.h" namespace KScope { namespace Core { /** * A process with a state-machine parser. * @author Elad Lahav */ class Process : public QProcess, public Parser::StateMachine { Q_OBJECT public: Process(QObject* parent = 0); ~Process(); void setDeleteOnExit(); signals: void parseError(); protected slots: virtual void handleFinished(int, QProcess::ExitStatus); virtual void handleError(QProcess::ProcessError); virtual void handleStateChange(QProcess::ProcessState); private: QString stdOut_; bool deleteOnExit_; private slots: void readStandardOutput(); void readStandardError(); }; } } #endif // __CORE_PROCESS_H kscope-1.9.4/core/core.pro0000644000175000001440000000151111156714354014577 0ustar elahavusersinclude(../config) TEMPLATE = lib TARGET = kscope_core CONFIG += dll # Input HEADERS += locationtreemodel.h \ locationmodel.h \ projectconfig.h \ filescanner.h \ filefilter.h \ queryview.h \ locationlistmodel.h \ parser.h \ exception.h \ project.h \ codebase.h \ codebasemodel.h \ globals.h \ process.h \ statemachine.h \ treeitem.h \ progressbar.h \ engine.h \ locationview.h \ textfilterdialog.h FORMS += progressbar.ui \ textfilterdialog.ui SOURCES += locationtreemodel.cpp \ locationmodel.cpp \ filescanner.cpp \ queryview.cpp \ locationlistmodel.cpp \ codebasemodel.cpp \ process.cpp \ progressbar.cpp \ locationview.cpp \ textfilterdialog.cpp RESOURCES = core.qrc target.path = $${INSTALL_PATH}/lib INSTALLS += target kscope-1.9.4/core/core.qrc0000644000175000001440000000125311156714354014567 0ustar elahavusers images/cancel.gif images/define.gif images/enum.gif images/enumerator.gif images/function.gif images/include.gif images/member.gif images/struct.gif images/typedef.gif images/union.gif images/variable.gif kscope-1.9.4/core/codebasemodel.cpp0000644000175000001440000001271311156714354016425 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "codebasemodel.h" namespace KScope { namespace Core { CodebaseModel::CodebaseModel(const Codebase* cbase, const QString& rootPath, QObject* parent) : QAbstractItemModel(parent), root_(rootPath) { // TODO: rootPath may be invalid. // Need to set root_ to "/", and ignore rootPath. // Add all files in the code base. AddFilesCallback cb(this); cbase->getFiles(cb); } CodebaseModel::~CodebaseModel() { } void CodebaseModel::addFiles(const QStringList& fileList) { // Add each of the files in the list to the tree structure. QStringList::ConstIterator itr; for (itr = fileList.begin(); itr != fileList.end(); ++itr) addFile(*itr); // It's much easier to just reset the model than to emit individual // dataChanged() signals, since files are added all over the tree. reset(); } /** * Converts the model's tree-structured data into a list of file paths. * @param fileList The list object to fill */ void CodebaseModel::getFiles(QStringList& fileList) const { getFiles(&root_, "", fileList); } QModelIndex CodebaseModel::index(int row, int column, const QModelIndex& parent) const { const ItemT* item; if (!parent.isValid()) { item = &root_; } else { item = indexData(parent); if (item == NULL) return QModelIndex(); } return createIndex(row, column, (void*)item->child(row)); } QModelIndex CodebaseModel::parent(const QModelIndex& index) const { if (!index.isValid()) return QModelIndex(); ItemT* item = indexData(index); if (item == NULL || item->parent() == &root_) return QModelIndex(); return createIndex(item->parent()->index(), 0, (void*)item->parent()); } QVariant CodebaseModel::headerData(int section, Qt::Orientation orient, int role) const { (void)section; if (orient != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); return tr("Path"); } int CodebaseModel::rowCount(const QModelIndex& parent) const { const TreeItem* item; if (!parent.isValid()) { item = &root_; } else { item = static_cast*>(parent.internalPointer()); if (item == NULL) return 0; } return item->childCount(); } int CodebaseModel::columnCount(const QModelIndex& parent) const { (void)parent; return 1; } QVariant CodebaseModel::data(const QModelIndex& index, int role) const { QString file; if (!index.isValid()) return QVariant(); if (role != Qt::DisplayRole) return QVariant(); TreeItem* item = static_cast*>(index.internalPointer()); if (item == NULL) return QVariant(); return item->data(); } void CodebaseModel::addFile(const QString& path) { // Remove the root path prefix. QString actPath; if (path.startsWith(root_.data())) actPath = path.mid(root_.data().length()); else actPath = path; // Dissect the file path into its directory and file components. QStringList pathParts = actPath.split('/', QString::SkipEmptyParts); // Descend down the tree, following the path components. ItemT* item = &root_; QStringList::iterator itr; for (itr = pathParts.begin(); itr != pathParts.end(); ++itr) { // Find a child of the current item corresponding to the component. // Create a new one if the child could not be found. ItemT* child; if ((child = item->findChild(*itr)) != NULL) item = child; else item = item->addChild(*itr); } } /** * An internal, recursive version of getFiles(). * @param item The current item in a DFS * @param path The path of the item's parent * @param fileList The list to fill */ void CodebaseModel::getFiles(const ItemT* item, const QString& path, QStringList& fileList) const { QString name = path + item->data(); if (item->childCount()) { // Add directory separator, if required. if (!name.endsWith("/")) name += "/"; // Descend to sub-directories. for (int i = 0; i < item->childCount(); i++) getFiles(item->child(i), name, fileList); } else { // Found a file, add to the list. fileList.append(name); } } #ifndef QT_NO_DEBUG void CodebaseModel::verify(const QModelIndex& parent) { int i; for (i = 0; i < rowCount(parent); i++) { QModelIndex child = index(i, 0, parent); if (child.parent() != parent) { QModelIndex cParent = child.parent(); qDebug() << cParent.row() << cParent.column() << cParent.internalPointer(); qDebug() << parent.row() << parent.column() << parent.internalPointer(); Q_ASSERT(false); } verify(child); } } #endif } } kscope-1.9.4/core/filescanner.cpp0000644000175000001440000001114111156714354016122 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "filescanner.h" namespace KScope { namespace Core { /** * Class constructor. * @param parent Owner object */ FileScanner::FileScanner(QObject* parent) : QObject(parent), followSymLinks_(false) { } /** * Class destructor. */ FileScanner::~FileScanner() { } /** * Starts a scan on a directory, using the given filter. * @param dir The directory to scan * @param filter The filter to use * @param recursive true for recursive scan, false otherwise * @return true if successful, false if the scan was aborted */ bool FileScanner::scan(const QDir& dir, const FileFilter& filter, bool recursive) { scanned_ = 0; fileList_.clear(); filter_ = filter; stop_ = false; // In a recursive scan, add only files under directories matching the filter // (starting with this one). QString path = dir.path(); if (!path.endsWith("/")) path += "/"; bool addFiles = recursive ? filter_.match(path, true) : true; qDebug() << "Scanning" << path << recursive << addFiles; return scan(dir, recursive, addFiles); } /** * Implements a directory scan. * @param dir The directory to scan * @param recursive true for recursive scan, false otherwise * @return true if successful, false if the scan was aborted */ bool FileScanner::scan(const QDir& dir, bool recursive, bool addFiles) { // Get a list of all entries in the directory. QFileInfoList infos = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); // Mark this directory as visited (if following symbolic links). if (followSymLinks_) visitedDirs_.insert(dir.absolutePath()); // Iterate over the list. QFileInfoList::Iterator itr; for (itr = infos.begin(); itr != infos.end(); ++itr) { // Make sure event processing continues during a long scan. qApp->processEvents(); if (stop_) return false; // Update and emit progress information. scanned_++; if ((scanned_ & 0xff) == 0) { if (!progressMessage_.isEmpty()) { QString msg = progressMessage_.arg(scanned_) .arg(fileList_.size()); emit progress(msg); } else { emit progress(scanned_, fileList_.size()); } } // Get the file's path. QString path = (*itr).filePath(); if ((*itr).isDir()) { // Directory: scan recursively, if needed. if (recursive) { // Handle symbolic links. if ((*itr).isSymLink()) { qDebug() << __func__ << (*itr).absoluteFilePath(); // If symbolic links are followed, make sure we do not // descend into an already-visited directory. if (!followSymLinks_ || visitedDirs_.contains((*itr).absoluteFilePath())) { continue; } } // Change directory. QDir childDir(dir); if (!childDir.cd((*itr).fileName())) continue; // Add a trailing "/" to directory names, so that the filter can // distinguish those from regular files. if (!path.endsWith('/')) path += "/"; // Scan recursively. // Filter behaviour for sub-directories: // 1. If an inclusion rule is matched, add files. // 2. If an exclusion rule is matched, do not add files. // 3. If no rule is matched, inherit the behaviour of the // current directory. if (!scan(childDir, true, filter_.match(path, addFiles))) return false; } } else if (addFiles) { // File: add to the file list if the path matches the filter. // The default match is set to false, so that files not matched by // any rule will not be added. if (filter_.match(path, false)) fileList_.append(path); } } return true; } } } kscope-1.9.4/core/project.h0000644000175000001440000002455311156714354014757 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_PROJECT_H #define __CORE_PROJECT_H #include #include #include #include "engine.h" #include "codebase.h" #include "exception.h" namespace KScope { namespace Core { /** * Abstract base-class for projects. * A project consists of a code base, and an engine that indexes it. * @author Elad Lahav */ class ProjectBase { public: ProjectBase() {} virtual ~ProjectBase() {} /** * Parameters for to configuring projects. */ struct Params { /** * The main project path. * The interpretation of this value is implementation-specific, but it * is expected that projects will store configuration and data files * in a directory corresponding to this path. */ QString projPath_; /** * The name of the project (to be displayed to the user). */ QString name_; /** * The root path of the code base. */ QString rootPath_; /** * A string used to initialise the engine (implementation-dependent). */ QString engineString_; /** * A string used to initialise the code base (implementation-dependent). */ QString codebaseString_; }; /** * Opens the project. */ virtual void open(Callback<>* cb) = 0; /** * Creates a new project. * @param params Project parameters */ virtual void create(const Params& params) = 0; /** * Modifies configuration parameters for this project. * @param params Project parameters */ virtual void updateConfig(const Params& params) = 0; /** * Closes the project. */ virtual void close() = 0; /** * @return The name of the project */ virtual QString name() const = 0; /** * @return The project path (where configuration files are stored) */ virtual QString path() const = 0; /** * @return The root path for the code base */ virtual QString rootPath() const = 0; /** * @return Pointer to the engine */ virtual Engine* engine() = 0; /** * @return Pointer to the code base */ virtual Codebase* codebase() = 0; }; /** * Class template for projects using a standard configuration file. * This is expected to be the (parameterised) base class for most project * implementations. * @author Elad Lahav */ template class Project : public ProjectBase { public: typedef Project SelfT; /** * Class constructor. * Attempts to read the name of the project from the given configuration * file. * This given file may not exist (e.g., if this object is used to create a * new project). The constructor will still succeed, but open() will fail. * @param confFileName The name of the configuration file * @param projPath The path of the directory holding the configuration * file (may be empty for new projects) */ Project(const QString& configFileName, const QString& projPath = QString()) : configFileName_(configFileName), loaded_(false), open_(false), engineOpenCB_(*this), codebaseOpenCB_(*this) { load(projPath); } /** * Class destructor. */ virtual ~Project() {} /** * Opens the project. * Initialises the code base and engine. * The configuration file must have been successfully loaded in the * constructor, or by a call to create(), for this method to succeed. * @throw Exception */ virtual void open(Callback<>* cb) { // Nothing to do if the project is already open. if (open_) return; // Make sure the configuration parameters were loaded. if (!loaded_) throw new Exception("Project parameters were not loaded"); openCB_ = cb; engineOpen_ = false; codebaseOpen_ = false; try { // Prepare the engine. engine_.open(params_.engineString_, &engineOpenCB_); // Open the code base. codebase_.open(params_.codebaseString_, &codebaseOpenCB_); } catch (Exception* e) { throw e; } } /** * Creates a new project. * Note that the project is not open after it has been created. * @param params Project parameters * @throw Exception */ virtual void create(const Params& params) { if (open_ || loaded_) throw new Exception("Cannot overwrite an existing project"); // Make sure the directory to contain the new configuration file // exists. Create it if necessary. QDir dir(params.projPath_); if (!dir.exists() && !dir.mkpath(params.projPath_)) { throw new Exception(QString("Failed to create the directory '%1'") .arg(params.projPath_)); } // Do not overwrite an existing project file. if (dir.exists(configFileName_)) { throw new Exception(QString("Cannot overwrite an existing " "project file '%1'") .arg(dir.filePath(configFileName_))); } // Copy the given parameters and update the configuration file. params_ = params; if (!params_.projPath_.endsWith("/")) params_.projPath_ += "/"; writeParams(); qDebug() << __func__ << dir.filePath(configFileName_); } /** * Applies a new set of configuration parameters to the project. * Not all parameters can be changed once a project is created. * At the very least, the project path must stay the same. An exception * is thrown if this parameter is modified. Inheriting classes can * throw exceptions if other read-only parameters are modified. Also, * inheriting classes should indicate whether the symbol database needs to * be rebuilt following the change to the project's parameters. * @param params The new set of parameters to install * @throw Exception */ virtual void updateConfig(const Params& params) { if (params.projPath_ != params_.projPath_) throw new Exception("The project path cannot be modified."); params_ = params; writeParams(); } /** * Marks the project as closed. * Note, however, that the configuration parameters are still loaded. */ virtual void close() { open_ = false; } /** * @return The name of the project */ virtual QString name() const { return params_.name_; } /** * @return The project path (where configuration files are stored) */ virtual QString path() const { return params_.projPath_; } /** * @return The root path for the project's code base */ virtual QString rootPath() const { return params_.rootPath_; } /** * @return A pointer to the engine object */ virtual Engine* engine() { return &engine_; } /** * @return A pointer to the code base object */ virtual Codebase* codebase() { return &codebase_; } /** * Retrieves a copy of the current configuration parameters. * @param params An object into which current values are copied */ void getCurrentParams(Params& params) const { params = params_; } protected: /** * The name of the project's configuration file. * The configuration file resides under the project path stored in the * configuration parameters. */ QString configFileName_; /** * Configuration parameters. */ Params params_; /** * Whether the project parameters were loaded from the configuration file. */ bool loaded_; /** * Whether the project is open. */ bool open_; /** * The indexing engine. */ EngineT engine_; /** * Whether the engine was opened. */ bool engineOpen_; /** * The code base. */ CodebaseT codebase_; /** * Whether the code base was opened. */ bool codebaseOpen_; /** * Callback object passed to open(). */ Callback<>* openCB_; struct EngineOpenCB : public Callback<> { SelfT& self_; EngineOpenCB(SelfT& self) : self_(self) {} void call() { self_.engineOpen_ = true; if (self_.codebaseOpen_) self_.finishOpen(); } } engineOpenCB_; struct CodebaseOpenCB : public Callback<> { SelfT& self_; CodebaseOpenCB(SelfT& self) : self_(self) {} void call() { self_.codebaseOpen_ = true; if (self_.engineOpen_) self_.finishOpen(); } } codebaseOpenCB_; /** * Reads project settings from the configuration file. */ virtual void load(const QString& projPath) { qDebug() << __func__ << projPath << configFileName_; // Do nothing if the project file does not exist (needs to be created). QFileInfo fi(QDir(projPath).filePath(configFileName_)); if (!fi.exists() || !fi.isReadable()) return; // Store the project path. // This is the directory holding the configuration file. params_.projPath_ = projPath; if (!params_.projPath_.endsWith("/")) params_.projPath_ += "/"; // Load parameters. QSettings projConfig(configPath(), QSettings::IniFormat); projConfig.beginGroup("Project"); params_.name_ = projConfig.value("Name", "").toString(); params_.rootPath_ = projConfig.value("RootPath", "/").toString(); params_.engineString_ = projConfig.value("EngineString").toString(); params_.codebaseString_ = projConfig.value("CodebaseString").toString(); projConfig.endGroup(); loaded_ = true; qDebug() << "Project loaded (name='" << params_.name_ << "')"; } /** * Writes the current project parameters in the configuration file. */ void writeParams() { // Write the configuration file. QSettings projConfig(configPath(), QSettings::IniFormat); projConfig.beginGroup("Project"); projConfig.setValue("Name", params_.name_); projConfig.setValue("RootPath", params_.rootPath_); projConfig.setValue("EngineString", params_.engineString_); projConfig.setValue("CodebaseString", params_.codebaseString_); projConfig.endGroup(); } void finishOpen() { open_ = true; if (openCB_) openCB_->call(); } inline QString configPath() { return params_.projPath_ + configFileName_; } }; } } #endif /* __CORE_PROJECT_H */ kscope-1.9.4/core/projectconfig.h0000644000175000001440000000442511156714354016141 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_PROJECTCONFIG_H__ #define __CORE_PROJECTCONFIG_H__ #include "project.h" namespace KScope { namespace Core { /** * Class template for creating project-specific configuration widgets. * A project dialogue can use this template to add a configuration page that * controls parameters in an implementation-dependent way. * The default implementation of the static functions does nothing. Use template * specialisation to create project-specific configuration widgets. * @author Elad Lahav */ template struct ProjectConfig { /** * Creates a configuration widget for the project. * @param project The project to use (NULL for a new project) * @param parent A parent for the new widget * @return The created widget (NULL by default) */ static QWidget* createConfigWidget(const ProjectT* project, QWidget* parent) { (void)project; (void)parent; return NULL; } /** * Fills a project parameters structure with data stored in a configuration * widget. * @param widget The configuration widget to use * @param params The structure to fill */ static void paramsFromWidget(QWidget* widget, ProjectBase::Params& params) { (void)widget; (void)params; } }; } // namespace Core } // namespace KScope #endif // __CORE_PROJECTCONFIG_H__ kscope-1.9.4/core/treeitem.h0000644000175000001440000001020011156714354015107 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CORE_TREEITEM_H__ #define __CORE_TREEITEM_H__ #include namespace KScope { namespace Core { /** * A generic ordered tree structure. * @author Elad Lahav */ template class TreeItem { public: typedef TreeItem SelfT; /** * Class constructor. * Creates a parent-less tree node. * @param data Node data */ TreeItem(DataT data = DataT()) : data_(data), parent_(NULL), index_(0) {} /** * Class destructor. */ ~TreeItem() {} /** * Data accessor. * @return The node's data */ DataT& data() { return data_; } /** * Data accessor (const version). * @return The node's data */ const DataT& data() const { return data_; } /** * Parent accessor. * @return The node's parent */ SelfT* parent() const { return parent_; } /** * Adds a child to this node. * @param data The child's data */ SelfT* addChild(DataT data) { SelfT child(data); child.parent_ = this; child.index_ = childList_.size(); childList_.append(child); return &childList_.last(); } /** * Child accessor. * @param index The ordinal number of the requested child * @return Pointer to the requested child, NULL if the index is out of * bounds */ SelfT* child(int index) { if (index < 0 || index >= childList_.size()) return NULL; return &childList_[index]; } /** * Child accessor (const version). * @param index The ordinal number of the requested child * @return Pointer to the requested child, NULL if the index is out of * bounds */ const SelfT* child(int index) const { if (index < 0 || index >= childList_.size()) return NULL; return &childList_[index]; } /** * Child-count accessor. * @return The number of children of this node */ int childCount() const { return childList_.size(); } /** * Self-index accessor. * @return The index of the node with respect to its parent */ int index() const { if (index_ == -1) index_ = parent_->childList_.indexOf(*this); return index_; } /** * Locates a child node holding the given data. * @param data Used for finding the node * @return The found child, NULL if no such child exists */ SelfT* findChild(DataT data) { for (int i = 0; i < childList_.size(); i++) { if (childList_[i].data_ == data) return &childList_[i]; } return NULL; } /** * Recursively removes all children nodes. */ void clear() { for (int i = 0; i < childList_.size(); i++) childList_[i].clear(); childList_.clear(); } /** * Two items are the same if and only if they are the same object. * @param other The item to compare with * @return true if the other item is equal to this one, false otherwise */ bool operator==(const SelfT& other) { return (this == &other); } private: /** * Node's data. */ DataT data_; /** * Node's parent, NULL for root. */ SelfT* parent_; /** * The index of this item in its parent's list. * A value of -1 indicates that the cached value is invalid, and needs to * be obtained from the parent. */ mutable int index_; /** * A list of children. */ QList childList_; }; } // namespace Core } // namespace KScope #endif // __CORE_TREEITEM_H__ kscope-1.9.4/COPYING0000644000175000001440000004313111156714355013235 0ustar elahavusers GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. kscope-1.9.4/INSTALL0000644000175000001440000000163711156714355013240 0ustar elahavusersBuilding and Installing KScope ============================== Prerequisites ------------- - Qt4 version 4.4.0 and above - QScintilla2 (http://www.riverbankcomputing.co.uk/software/qscintilla/download) - Standard build tools Configure --------- Edit the 'config' file as necessary. Please make sure that all paths are set up correctly before building KScope. Any changes to the configuration file require a fresh build (starting with an invocation of qmake). Build ----- In a shell, execute $ qmake $ make or $ make debug for a debug-enabled build. Install ------- Make sure you have the right permissions for copying files into the destination directory. Then execute $ make install Run --- The executable is called 'kscopeapp' and is located under INSTALL_PATH/bin. The shared libraries are under INSTALL_PATH/lib, so LD_LIBRARY_PATH needs to include this directory for the dynamic linker to find them. kscope-1.9.4/cscope/0000755000175000001440000000000011156714402013445 5ustar elahavuserskscope-1.9.4/cscope/crossref.cpp0000644000175000001440000001463411156714355016016 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include "crossref.h" #include "ctags.h" namespace KScope { namespace Cscope { /** * Class constructor. * @param parent Parent object */ Crossref::Crossref(QObject* parent) : Core::Engine(parent), status_(Unknown) { } /** * Class destructor. */ Crossref::~Crossref() { } /** * Opens a cscope cross-reference database. * The method expects to find a 'cscope.out' file under the given path. * The path is stored and used for all database operations. * The initialisation string should be colon-delimited, where the first section * is the project path (includes the cscope.out and cscope.files files), * followed by command-line arguments to Cscope (only the ones that apply to * building the database). * @param initString The initialisation string * @throw Exception */ void Crossref::open(const QString& initString, Core::Callback<>* cb) { // Parse the initialisation string. QStringList args = initString.split(":", QString::SkipEmptyParts); QString path = args.takeFirst(); qDebug() << __func__ << initString << path; // Make sure the path exists. QDir dir(path); if (!dir.exists()) throw new Core::Exception("Database directory does not exist"); // Check if the cross-reference file exists. // If not, the databsae needs to be built. Otherwise, it is ready for // querying, but needs to be rebuilt. // We also ensure that if it exists it is readable. QFileInfo fi(dir, "cscope.out"); Status status; if (!fi.exists()) status = Build; else if (!fi.isReadable()) throw new Core::Exception("Cannot read the 'cscope.out' file"); else status = Ready; // Handle reopening with different parameters (i.e., after a change to the // project parameters). if (status_ != Unknown) { if ((path != path_) || args != args_) status = Rebuild; } // Store arguments for running Cscope. path_ = path; args_ = args; status_ = status; if (cb) cb->call(); } /** * Builds a list of fields for each query type. * The list specifies the fields that carry useful information for the given * type of query. * @param type Query type * @return A list of Location structure fields */ QList Crossref::queryFields(Core::Query::Type type) const { QList fieldList; switch (type) { case Core::Query::FindFile: fieldList << Core::Location::File; break; case Core::Query::Text: case Core::Query::IncludingFiles: fieldList << Core::Location::File << Core::Location::Line << Core::Location::Text; break; case Core::Query::Definition: fieldList << Core::Location::TagName << Core::Location::File << Core::Location::Line << Core::Location::Text; break; case Core::Query::References: case Core::Query::CalledFunctions: case Core::Query::CallingFunctions: fieldList << Core::Location::Scope << Core::Location::File << Core::Location::Line << Core::Location::Text; break; case Core::Query::LocalTags: fieldList << Core::Location::TagName << Core::Location::Scope << Core::Location::Line << Core::Location::TagType; break; default: ; } return fieldList; } /** * Starts a Cscope query. * Creates a new Cscope process to handle the query. * @param conn Connection object to attach to the new process * @param query Query information * @throw Exception */ void Crossref::query(Core::Engine::Connection* conn, const Core::Query& query) const { Cscope::QueryType type; // Translate the requested type into a Cscope query number. switch (query.type_) { case Core::Query::Text: if (query.flags_ & Core::Query::RegExp) type = Cscope::EGrepPattern; else type = Cscope::Text; break; case Core::Query::References: type = Cscope::References; break; case Core::Query::Definition: type = Cscope::Definition; break; case Core::Query::CalledFunctions: type = Cscope::CalledFunctions; break; case Core::Query::CallingFunctions: type = Cscope::CallingFunctions; break; case Core::Query::FindFile: type = Cscope::FindFile; break; case Core::Query::IncludingFiles: type = Cscope::IncludingFiles; break; case Core::Query::LocalTags: { Ctags* ctags = new Ctags(); ctags->setDeleteOnExit(); ctags->query(conn, query.pattern_); return; } default: // Query type is not supported. // TODO: What happens if an exception is thrown from within a slot? throw new Core::Exception(QString("Unsupported query type '%1") .arg(query.type_)); } // Create a new Cscope process object, and start the query. Cscope* cscope = new Cscope(); cscope->setDeleteOnExit(); cscope->query(conn, path_, type, query.pattern_); } /** * Starts a Cscope build process. * @param conn Connection object to attach to the new process */ void Crossref::build(Core::Engine::Connection* conn) const { // Create the Cscope process object. Cscope* cscope = new Cscope(); cscope->setDeleteOnExit(); // Need to update the status upon successful termination. connect(cscope, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(buildProcessFinished(int, QProcess::ExitStatus))); // Start the build process. cscope->build(conn, path_, args_); } void Crossref::buildProcessFinished(int code, QProcess::ExitStatus status) { if ((code == 0) && (status == QProcess::NormalExit)) status_ = Ready; } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/configwidget.cpp0000644000175000001440000000232611156714355016634 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "configwidget.h" namespace KScope { namespace Cscope { ConfigWidget::ConfigWidget(QWidget* parent) : QWidget(parent), Ui::ConfigWidget() { setupUi(this); } ConfigWidget::~ConfigWidget() { } } } kscope-1.9.4/cscope/cscope.cpp0000644000175000001440000001400711156714355015436 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "cscope.h" namespace KScope { namespace Cscope { QString Cscope::execPath_("/usr/bin/cscope"); /** * Class constructor. * Creates the parser objects used for parsing Cscope output. */ Cscope::Cscope() : Process(), conn_(NULL), buildInitState_("BuildInit"), buildProgState_("BuildProgress"), queryProgState_("QueryProgress"), queryResultState_("QueryResults") { addRule(buildInitState_, Parser::Literal("Building cross-reference...\n"), buildProgState_); addRule(buildProgState_, Parser::Literal("> Building symbol database ") << Parser::Number() << Parser::Literal(" of ") << Parser::Number() << Parser::Literal("\n"), buildProgState_, ProgAction(*this, tr("Building database..."))); addRule(queryProgState_, Parser::Literal("> Symbols matched ") << Parser::Number() << Parser::Literal(" of ") << Parser::Number() << Parser::Literal("\n"), queryProgState_, ProgAction(*this, tr("Querying..."))); addRule(queryProgState_, Parser::Literal("> Possible references retrieved ") << Parser::Number() << Parser::Literal(" of ") << Parser::Number() << Parser::Literal("\n"), queryProgState_, ProgAction(*this, tr("Querying..."))); addRule(queryProgState_, Parser::Literal("> Search ") << Parser::Number() << Parser::Literal(" of ") << Parser::Number() << Parser::Literal("\n"), queryProgState_, ProgAction(*this, tr("Querying..."))); addRule(queryProgState_, Parser::Literal("cscope: ") << Parser::Number() << Parser::Literal(" lines\n"), queryResultState_, QueryEndAction(*this)); addRule(queryResultState_, Parser::String<>(' ') << Parser::Whitespace() << Parser::String<>(' ') << Parser::Whitespace() << Parser::Number() << Parser::Whitespace() << Parser::String<>('\n') << Parser::Literal("\n"), queryResultState_, QueryResultAction(*this)); } /** * Class destructor. */ Cscope::~Cscope() { } /** * Starts a Cscope query process. * The process performs a one-time, line-oriented query on the database, without * rebuilding it. * @param conn A connection object used for reporting progress and data * @param path The directory to execute under * @param type The type of query to run * @param pattern The pattern to query * @throw Exception */ void Cscope::query(Core::Engine::Connection* conn, const QString& path, QueryType type, const QString& pattern) { // Abort if a process is already running. if (state() != QProcess::NotRunning || conn_ != NULL) throw Core::Exception("Process already running"); // Prepare the argument list. QStringList args; args << "-d"; args << "-v"; args << QString("-L%1").arg(type); args << pattern; setWorkingDirectory(path); // Initialise parsing. conn_ = conn; conn_->setCtrlObject(this); setState(queryProgState_); locList_.clear(); type_ = type; // Start the process. qDebug() << "Running" << execPath_ << args << "in" << path; start(execPath_, args); } /** * Starts a Cscope build process. * @param conn A connection object used for reporting progress and data * @param path The directory to execute under * @param buildArgs Command-line arguments for building the database * @throw Exception */ void Cscope::build(Core::Engine::Connection* conn, const QString& path, const QStringList& buildArgs) { // Abort if a process is already running. if (state() != QProcess::NotRunning || conn_ != NULL) throw Core::Exception("Process already running"); // TODO: Make the Cscope path configurable. QString prog = "/usr/bin/cscope"; // Prepare the argument list. QStringList args = buildArgs; args << "-b"; args << "-v"; setWorkingDirectory(path); // Initialise parsing. conn_ = conn; conn_->setCtrlObject(this); setState(buildInitState_); // Start the process. qDebug() << "Running cscope:" << args << "in" << path; start(prog, args); } /** * Called when the process terminates. * @param code The exit code of the process * @param status Used to indicate process crashes */ void Cscope::handleFinished(int code, QProcess::ExitStatus status) { Process::handleFinished(code, status); // Hand over data to the other side of the connection. if (!locList_.isEmpty()) conn_->onDataReady(locList_); // Signal normal termination. conn_->onFinished(); // Detach from the connection object. conn_->setCtrlObject(NULL); conn_ = NULL; } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/engineconfigwidget.ui0000644000175000001440000000260011156714355017650 0ustar elahavusers EngineConfigWidget 0 0 400 300 Cscope Cscope path Ctags path Qt::Vertical 20 214 kscope-1.9.4/cscope/ctags.h0000644000175000001440000001116711156714355014734 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_CTAGS_H__ #define __CSCOPE_CTAGS_H__ #include #include #include namespace KScope { namespace Cscope { /** * Front-end to a Ctags process. * Since Cscope does not provide a query type for local tags, we use a Ctags * process to provide this information. Thus, whenever a query of this type is * selected for execution by the Cscope::Crossref engine, the engine creates a * Ctags object instead of a Cscope one. * @author Elad Lahav */ class Ctags : public Core::Process, public Core::Engine::Controlled { public: Ctags(); ~Ctags(); void query(Core::Engine::Connection*, const QString&); /** * Stops a running process. */ virtual void stop() { kill(); } static QString execPath_; protected slots: virtual void handleFinished(int, QProcess::ExitStatus); private: /** * The current connection object, used to communicate progress and result * information. */ Core::Engine::Connection* conn_; /** * List of locations. * The list is constructed when result lines are parsed. */ Core::LocationList locList_; /** * State for parsing the single-character tag type. */ State tagTypeState_; /** * State for parsing possible attributes. */ State attrListState_; /** * Functor for the initial-state transition-function. */ struct ParseAction { /** * Struct constructor. * @param self The owner Ctags object */ ParseAction(Ctags& self) : self_(self) {} /** * Functor operator. * Parses result lines. * @param capList List of captured strings */ void operator()(const Parser::CapList& capList) const { // Fill-in a Location object, using the parsed result information. Core::Location loc; loc.tag_.name_ = capList[0].toString(); loc.file_ = capList[1].toString(); loc.line_ = capList[2].toUInt(); loc.column_ = 0; // Translate a Ctags type character into a tag type value. switch (capList[3].toString().at(0).toLatin1()) { case 'v': loc.tag_.type_ = Core::Tag::Variable; break; case 'f': loc.tag_.type_ = Core::Tag::Function; break; case 's': loc.tag_.type_ = Core::Tag::Struct; break; case 'u': loc.tag_.type_ = Core::Tag::Union; break; case 'm': loc.tag_.type_ = Core::Tag::Member; break; case 'g': loc.tag_.type_ = Core::Tag::Enum; break; case 'e': loc.tag_.type_ = Core::Tag::Enumerator; break; case 'd': loc.tag_.type_ = Core::Tag::Define; break; case 't': loc.tag_.type_ = Core::Tag::Typedef; break; default: loc.tag_.type_ = Core::Tag::UnknownTag; } // Add to the list of parsed locations. self_.locList_.append(loc); } /** * The owner Ctags object. */ Ctags& self_; }; /** * Functor for the initial-state transition-function. */ struct ParseAttributeAction { /** * Struct constructor. * @param self The owner Ctags object */ ParseAttributeAction(Ctags& self) : self_(self) {} /** * Functor operator. * Parses result lines. * @param capList List of captured strings */ void operator()(const Parser::CapList& capList) const { Core::Location& loc = self_.locList_.last(); for (int i = 0; i < capList.size(); i++) { // Get the attribute name. QString attr = capList[i++].toString(); if (capList.size() == i) break; // Get the attribute value. QString val = capList[i].toString(); if ((attr == "struct") || (attr == "union") || (attr == "enum")) { loc.tag_.scope_ = val; } } } /** * The owner Ctags object. */ Ctags& self_; }; }; } // namespace Cscope } // namespace KScope #endif // __CSCOPE_CTAGS_H__ kscope-1.9.4/cscope/files.cpp0000644000175000001440000000617211156714355015270 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include "files.h" namespace KScope { namespace Cscope { /** * Class constructor. * @param parent Parent object */ Files::Files(QObject* parent) : Core::Codebase(parent), writable_(false) { } /** * Class destructor. */ Files::~Files() { } /** * Creates a new cscope.files file. * @param path The project path under which to create the new file */ void Files::create(const QString& path) { // Make sure the directory exists. QDir dir(path); if (!dir.exists()) throw new Core::Exception("File list directory does not exist"); // Open the file for writing. QFile file(dir.filePath("cscope.files")); if (!file.open(QIODevice::WriteOnly)) throw Core::Exception("Failed to create the 'cscope.files' file"); path_ = dir.filePath("cscope.files"); writable_ = true; empty_ = true; } void Files::open(const QString& path, Core::Callback<>* cb) { // Make sure the directory exists. QDir dir(path); if (!dir.exists()) throw new Core::Exception("File list directory does not exist"); // Check if the file exists. QFileInfo fi(dir, "cscope.files"); if (fi.exists()) { // Yes, make sure it can be read. if (!fi.isReadable()) throw new Core::Exception("Cannot open 'cscope.files' for reading"); path_ = dir.filePath("cscope.files"); writable_ = fi.isWritable(); empty_ = (fi.size() == 0); } else { // No, create a new file. try { create(path); } catch (Core::Exception* e) { throw e; } } if (cb) cb->call(); } void Files::save(const QString& path) { (void)path; } void Files::getFiles(Core::Callback& cb) const { QFile file(path_); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream strm(&file); while (!strm.atEnd()) cb.call(strm.readLine()); } void Files::setFiles(const QStringList& fileList) { QFile file(path_); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream strm(&file); QStringList::ConstIterator itr; for (itr = fileList.begin(); itr != fileList.end(); ++itr) strm << *itr << endl; empty_ = fileList.isEmpty(); } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/engineconfigwidget.h0000644000175000001440000000272711156714355017474 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSOCPE_ENGINECONFIGWIDGET_H__ #define __CSCOPE_ENGINECONFIGWIDGET_H__ #include "ui_engineconfigwidget.h" namespace KScope { namespace Cscope { class EngineConfigWidget : public QWidget, public Ui::EngineConfigWidget { Q_OBJECT public: EngineConfigWidget(QWidget*); ~EngineConfigWidget(); QString cscopePath() { return cscopePathEdit_->text(); } QString ctagsPath() { return ctagsPathEdit_->text(); } }; } // namespace Cscope } // namesapce KScope #endif // __CSCOPE_ENGINECONFIGWIDGET_H__ kscope-1.9.4/cscope/engineconfigwidget.cpp0000644000175000001440000000236511156714355020025 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "engineconfigwidget.h" namespace KScope { namespace Cscope { EngineConfigWidget::EngineConfigWidget(QWidget* parent) : QWidget(parent), Ui::EngineConfigWidget() { setupUi(this); } EngineConfigWidget::~EngineConfigWidget() { } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/files.h0000644000175000001440000000370311156714355014732 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_FILES_H__ #define __CSCOPE_FILES_H__ #include namespace KScope { namespace Cscope { /** * Manages a cscope.files file. * A cscope.files file is a text file containing the name of each file in the * project on a separate line. * @author Elad Lahav */ class Files : public Core::Codebase { Q_OBJECT public: Files(QObject* parent = NULL); ~Files(); void create(const QString&); // Core::Codebase implementation. void open(const QString&, Core::Callback<>*); void save(const QString&); void getFiles(Core::Callback&) const; void setFiles(const QStringList&); bool canModify() { return writable_; } bool needFiles() { return writable_ && empty_; } private: /** * The path to the cscope.files file. */ QString path_; /** * Whether the file can be written to. */ bool writable_; /** * Whether the file contains any data. */ bool empty_; }; } // namespace Cscope } // namespace KScope #endif // __CSCOPE_FILES_H__ kscope-1.9.4/cscope/crossref.h0000644000175000001440000000735111156714355015461 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_CROSSREF_H__ #define __CSCOPE_CROSSREF_H__ #include "cscope.h" #include "ctags.h" #include "engineconfigwidget.h" namespace KScope { namespace Cscope { /** * Manages a Cscope cross-reference database. * The cross-reference database generated by Cscope is stored in a cscope.out * file, as well as optional inverted-index files. This class creates * independent Cscope processes used to query and build these files. When * building the cross-reference database, Cscope uses temporary files, so that * the existing database can still be queried. * @author Elad Lahav */ class Crossref : public Core::Engine { Q_OBJECT public: Crossref(QObject* parent = 0); ~Crossref(); void open(const QString&, Core::Callback<>*); /** * @return The current status of the database. */ Status status() const { return status_; } QList queryFields(Core::Query::Type) const; public slots: void query(Core::Engine::Connection*, const Core::Query&) const; void build(Core::Engine::Connection*) const; const QString& path() { return path_; } private: /** * The path of the directory containing the cscope.out file. */ QString path_; /** * Command-line arguments to Cscope. */ QStringList args_; /** * The current status of the database. */ Status status_; private slots: void buildProcessFinished(int, QProcess::ExitStatus); }; } // namespace Cscope namespace Core { /** * Provides configuration management for the Cscope/Ctags engine. */ template<> struct EngineConfig { static QString name() { return "Cscope"; } static void getConfig(KeyValuePairs& confParams) { confParams["CscopePath"] = Cscope::Cscope::execPath_; confParams["CtagsPath"] = Cscope::Ctags::execPath_; } static void setConfig(const KeyValuePairs& confParams) { QString cscopePath = confParams["CscopePath"].toString(); if (!cscopePath.isEmpty()) Cscope::Cscope::execPath_ = cscopePath; QString ctagsPath = confParams["CtagsPath"].toString(); if (!ctagsPath.isEmpty()) Cscope::Ctags::execPath_ = ctagsPath; } static QWidget* createConfigWidget(QWidget* parent) { Cscope::EngineConfigWidget* widget = new Cscope::EngineConfigWidget(parent); qDebug() << Cscope::Cscope::execPath_ << Cscope::Ctags::execPath_; widget->cscopePathEdit_->setText(Cscope::Cscope::execPath_); widget->ctagsPathEdit_->setText(Cscope::Ctags::execPath_); return widget; } static void configFromWidget(QWidget* widget) { Cscope::EngineConfigWidget* configWidget = dynamic_cast(widget); if (configWidget == NULL) return; Cscope::Cscope::execPath_ = configWidget->cscopePath(); Cscope::Ctags::execPath_ = configWidget->ctagsPath(); } }; } // namespace Core } // namespace KScope #endif // __CSCOPE_CROSSREF_H__ kscope-1.9.4/cscope/managedproject.cpp0000644000175000001440000000415511156714355017150 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "managedproject.h" namespace KScope { namespace Cscope { /** * Class constructor. * @param projPath The directory to use for this project */ ManagedProject::ManagedProject(const QString& projPath) : Core::Project("project.conf", projPath) { } /** * Class destructor. */ ManagedProject::~ManagedProject() { } /** * Creates a new Cscope managed project. * @param params Configuration parameters for the new project * @throw Exception */ void ManagedProject::create(const Core::ProjectBase::Params& params) { try { Core::Project::create(params); Files().create(params.projPath_); } catch (Core::Exception* e) { throw e; } } /** * Modified configuration parameters for this project. * @param params Updated configuration parameters. * @throw Exception */ void ManagedProject::updateConfig(const Core::ProjectBase::Params& params) { try { // Base class implementation. Core::Project::updateConfig(params); // Apply changes to the engine. engine_.open(params.engineString_, NULL); } catch (Core::Exception* e) { throw e; } } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/cscope.pro0000644000175000001440000000105511156714355015453 0ustar elahavusersinclude(../config) TEMPLATE = lib TARGET = kscope_cscope DEPENDPATH += ". ../core" CONFIG += dll # Input HEADERS += engineconfigwidget.h \ ctags.h \ configwidget.h \ managedproject.h \ crossref.h \ cscope.h \ files.h FORMS += configwidget.ui \ engineconfigwidget.ui SOURCES += engineconfigwidget.cpp \ ctags.cpp \ configwidget.cpp \ managedproject.cpp \ crossref.cpp \ cscope.cpp \ files.cpp INCLUDEPATH += .. \ . LIBS += -L../core -lkscope_core target.path = $${INSTALL_PATH}/lib INSTALLS += target kscope-1.9.4/cscope/managedproject.h0000644000175000001440000000714211156714355016614 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_MANAGEDPROJECT_H__ #define __CSCOPE_MANAGEDPROJECT_H__ #include #include #include "crossref.h" #include "files.h" #include "configwidget.h" namespace KScope { namespace Cscope { /** * A managed Cscope project. * This is a managed project, since KScope has control over the code base, which * is kept as a cscope.files file. * @author Elad Lahav */ class ManagedProject : public Core::Project { public: ManagedProject(const QString& projPath = QString()); virtual ~ManagedProject(); void create(const Params&); void updateConfig(const Params&); }; } namespace Core { /** * Template specialisation for Cscope managed projects. * @author Elad Lahav */ template<> struct ProjectConfig { /** * Creates a Cscope configuration widget. * @param project The project for which parameters are shown (NULL for a * new project) * @param parent The parent widget * @return A new configuration widget */ static QWidget* createConfigWidget(const Cscope::ManagedProject* project, QWidget* parent) { Cscope::ConfigWidget* widget = new Cscope::ConfigWidget(parent); if (project) { // Existing project: set widget controls to reflect current // configuration. ProjectBase::Params params; project->getCurrentParams(params); QStringList args = params.engineString_.split(":"); widget->kernelCheck_->setChecked(args.contains("-k")); widget->invIndexCheck_->setChecked(args.contains("-q")); widget->compressCheck_->setChecked(!args.contains("-c")); } else { // New project: set default configuration. widget->kernelCheck_->setChecked(false); widget->invIndexCheck_->setChecked(true); widget->compressCheck_->setChecked(true); } return widget; } /** * Updates a project parameters structure to reflect the current selections * in a configuration widget. * @param widget The widget from which parameters are taken * @param params The structure to fill */ static void paramsFromWidget(QWidget* widget, ProjectBase::Params& params) { params.engineString_ = params.projPath_; params.codebaseString_ = params.projPath_; Cscope::ConfigWidget* confWidget = dynamic_cast(widget); if (confWidget) { if (confWidget->kernelCheck_->isChecked()) params.engineString_ += ":-k"; if (confWidget->invIndexCheck_->isChecked()) params.engineString_ += ":-q"; if (!confWidget->compressCheck_->isChecked()) params.engineString_ += ":-c"; } } }; } // namespace Cscope } // namespace KScope #endif // __CSCOPE_MANAGEDPROJECT_H kscope-1.9.4/cscope/cscope.h0000644000175000001440000001324011156714355015101 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_CSCOPE_H__ #define __CSCOPE_CSCOPE_H__ #include #include #include namespace KScope { namespace Cscope { /** * Front-end to a Cscope process. * This object can be used for both querying and building the Cscope * cross-reference file. * @author Elad Lahav */ class Cscope : public Core::Process, public Core::Engine::Controlled { public: Cscope(); ~Cscope(); /** * Cscope query types. * These are enumerated by the numeric value assigned to each query type * in Cscope's command-line interface (i.e., the parameter to the -L * option). */ enum QueryType { References = 0, Definition = 1, CalledFunctions = 2, CallingFunctions = 3, Text = 4, EGrepPattern = 6, FindFile = 7, IncludingFiles = 8 }; void query(Core::Engine::Connection*, const QString&, QueryType, const QString&); void build(Core::Engine::Connection*, const QString&, const QStringList&); /** * Stops a query/build process. */ virtual void stop() { kill(); } static QString execPath_; protected slots: virtual void handleFinished(int, QProcess::ExitStatus); private: /** * The current connection object, used to communicate progress and result * information. */ Core::Engine::Connection* conn_; /** * Total number of result lines. */ uint resNum_; /** * Number of parsed result lines (used to provide parsing progress * information). */ uint resParsed_; /** * Initial state for when building the database. */ State buildInitState_; /** * Build progress state. */ State buildProgState_; /** * Query progress state. */ State queryProgState_; /** * Query results state. */ State queryResultState_; /** * List of locations. * The list is constructed when result lines are parsed. */ Core::LocationList locList_; /** * The type of the current query. */ QueryType type_; /** * Functor for progress-states transition-functions. */ struct ProgAction { /** * Struct constructor. * @param self The owner Cscope object * @param text Used to build progress messages */ ProgAction(Cscope& self, const QString& text) : self_(self), text_(text) {} /** * Functor operator. * Provides a call-back into the connection's onProgress() method. * @param capList List of captured strings */ void operator()(const Parser::CapList& capList) const { self_.conn_->onProgress(text_, capList[0].toUInt(), capList[1].toUInt()); } /** * The owner Cscope object. */ Cscope& self_; /** * Used to build progress messages */ QString text_; }; /** * Functor for the end-of-query-state transition-function. */ struct QueryEndAction { /** * Struct constructor. * @param self The owner Cscope object */ QueryEndAction(Cscope& self) : self_(self) {} /** * Functor operator. * Provides a call-back into the connection's onProgress() method. * @param capList List of captured strings */ void operator()(const Parser::CapList& capList) const { self_.resNum_ = capList[0].toUInt(); self_.resParsed_ = 0; self_.conn_->onProgress(tr("Parsing..."), 0, self_.resNum_); } /** * The owner Cscope object. */ Cscope& self_; }; /** * Functor for the query-result-state transition-function. */ struct QueryResultAction { /** * Struct constructor. * @param self The owner Cscope object */ QueryResultAction(Cscope& self) : self_(self) {} /** * Functor operator. * Parses result lines. * @param capList List of captured strings */ void operator()(const Parser::CapList& capList) const { // Fill-in a Location object, using the parsed result information. Core::Location loc; loc.file_ = capList[0].toString(); loc.line_ = capList[2].toUInt(); loc.column_ = 0; loc.text_ = capList[3].toString(); loc.tag_.type_ = Core::Tag::UnknownTag; // Cscope's "Scope" result field should be handled differently // for each query type. switch (self_.type_) { case Cscope::References: case Cscope::CalledFunctions: case Cscope::CallingFunctions: loc.tag_.scope_ = capList[1].toString(); break; case Cscope::Definition: loc.tag_.name_ = capList[1].toString(); break; default: ; } // Add to the list of parsed locations. self_.locList_.append(loc); self_.resParsed_++; // Provide progress information for result-parsing. if ((self_.resParsed_ & 0xff) == 0) { self_.conn_->onProgress(tr("Parsing..."), self_.resParsed_, self_.resNum_); } } /** * The owner Cscope object. */ Cscope& self_; }; }; } // namespace Cscope } // namespace KScope #endif // __CSCOPE_CSCOPE_H__ kscope-1.9.4/cscope/ctags.cpp0000644000175000001440000000652111156714355015265 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "ctags.h" namespace KScope { namespace Cscope { QString Ctags::execPath_ = "/usr/bin/ctags"; /** * Class constructor. */ Ctags::Ctags() : Process(), conn_(NULL) { // Parse a line starting with the following format: // TAG_NAME\tFILE_NAME\tLINE_NUMBER;"\tTAG_TYPE addRule(initState_, Parser::String<>('\t') << Parser::Literal("\t") << Parser::String<>('\t') << Parser::Literal("\t") << Parser::Number() << Parser::Literal(";\"\t") << Parser::String(QRegExp("[\t\n]")), attrListState_, ParseAction(*this)); // Attribute lists: // *(\tATTRIBUTE_NAME:[ATTRIBUTE_VALUE])\n addRule(attrListState_, Parser::Literal("\t") << Parser::String<>(':') << Parser::Literal(":") << Parser::String(QRegExp("[\t\n]")), attrListState_, ParseAttributeAction(*this)); addRule(attrListState_, Parser::Literal("\n"), initState_); } /** * Class destructor. */ Ctags::~Ctags() { } void Ctags::query(Core::Engine::Connection* conn, const QString& file) { // Abort if a process is already running. if (state() != QProcess::NotRunning || conn_ != NULL) throw Core::Exception("Process already running"); // Prepare the argument list. QStringList args; args << "-n" // use line numbers instead of patterns << "--fields=+s" // add scope information << "--sort=no" // do not sort by tag name << "-f" << "-" // output to stdout instead of a file << file; // Initialise parsing. conn_ = conn; conn_->setCtrlObject(this); locList_.clear(); // Start the process. qDebug() << "Running" << execPath_ << args; start(execPath_, args); } /** * Called when the process terminates. * @param code The exit code of the process * @param status Used to indicate process crashes */ void Ctags::handleFinished(int code, QProcess::ExitStatus status) { Process::handleFinished(code, status); // Hand over data to the other side of the connection. if (!locList_.isEmpty()) conn_->onDataReady(locList_); // Signal normal termination. conn_->onFinished(); // Detach from the connection object. conn_->setCtrlObject(NULL); conn_ = NULL; } } // namespace Cscope } // namespace KScope kscope-1.9.4/cscope/configwidget.h0000644000175000001440000000243611156714355016303 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __CSCOPE_CONFIGWIDGET_H__ #define __CSCOPE_CONFIGWIDGET_H__ #include #include "ui_configwidget.h" namespace KScope { namespace Cscope { class ConfigWidget : public QWidget, public Ui::ConfigWidget { Q_OBJECT public: ConfigWidget(QWidget*); ~ConfigWidget(); }; } } #endif // __CSCOPECONFIGWIDGET_H__ kscope-1.9.4/cscope/configwidget.ui0000644000175000001440000000264711156714355016475 0ustar elahavusers ConfigWidget 0 0 400 300 Cscope Configuration Kernel project (do not index user-space include files) Build inverted index false Compress database false Qt::Vertical 20 203 kscope-1.9.4/kscope.pro0000644000175000001440000000021211156714355014201 0ustar elahavusersinclude(config) TEMPLATE = subdirs # Directories SUBDIRS += core cscope editor app message(Installation root path is $${INSTALL_PATH}) kscope-1.9.4/editor/0000755000175000001440000000000011156714402013457 5ustar elahavuserskscope-1.9.4/editor/actions.h0000644000175000001440000000701011156714354015274 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_ACTIONS_H__ #define __EDITOR_ACTIONS_H__ #include #include #include #include "editor.h" namespace KScope { namespace Editor { /** * Manages actions for an editor. * This class provides a slot proxy for an editor object. This is beneficial in * a multi-editor environment, where the active window changes constantly. The * alternative would be to disconnect and connect editor slots directly, which * is inefficient. * @author Elad Lahav */ class Actions : public QObject { Q_OBJECT public: Actions(QObject* parent = 0); ~Actions(); void setupMenu(QMenu*); void setEditor(Editor*); public slots: /** * Copies the current selection to the clipboard. */ void copy() { editor_->copy(); } /** * Copies the current selection to the clipboard and deletes it from the * text. */ void cut() { editor_->cut(); } /** * Paste clipboard contents in the current cursor position. */ void paste() { editor_->paste(); } /** * Cancels the last operation. */ void undo() { editor_->undo(); } /** * Re-executes a cancelled operation. */ void redo() { editor_->redo(); } /** * Prompts the user for a pattern to search in the file. */ void find() { editor_->search(); } /** * Repeats the last search, starting at the current potision. */ void findNext() { editor_->searchNext(); } /** * Prompts the user for a line number, and moves the cursor to that line. */ void gotoLine() { editor_->gotoLine(); } /** * Moves the cursor to the beginning of the current block. */ void gotoBlockBegin() { editor_->gotoBlockBegin(); } signals: /** * Emitted when a new editor is set. * @param valid true if the editor object pointer is valid, false otherwise */ void editorChanged(bool valid); private: /** * The managed editor object. * May be NULL, in which case all actions should be disabled. */ Editor* editor_; /** * Copy text action. */ QAction* actCopy_; /** * Cut text action. */ QAction* actCut_; /** * Paste text action. */ QAction* actPaste_; /** * Undo action. */ QAction* actUndo_; /** * Redo action. */ QAction* actRedo_; /** * Search text action. */ QAction* actFind_; /** * Repeat search action. */ QAction* actFindNext_; /** * Go to line action. */ QAction* actGotoLine_; QAction* actBlockBegin_; /** * Allows all actions to be enabled when the editor pointer is valid, and * disabled when it does not. */ QActionGroup* editorGroup_; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_ACTIONS_H__ kscope-1.9.4/editor/editor.pro0000644000175000001440000000127611156714354015503 0ustar elahavusersinclude(../config) TEMPLATE = lib TARGET = kscope_editor DEPENDPATH += ". ../core" CONFIG += dll # Input HEADERS += viscintilla.h \ actions.h \ lexerstyledelegate.h \ lexerstylemodel.h \ editor.h \ configdialog.h \ fileiothread.h \ findtextdialog.h \ config.h FORMS += configdialog.ui \ findtextdialog.ui SOURCES += viscintilla.cpp \ actions.cpp \ lexerstylemodel.cpp \ config.cpp \ editor.cpp \ configdialog.cpp \ findtextdialog.cpp INCLUDEPATH += .. \ $${QSCI_ROOT_PATH}/include/Qsci \ . LIBS += -L../core \ -lkscope_core \ -L$${QSCI_ROOT_PATH}/lib \ -lqscintilla2 target.path = $${INSTALL_PATH}/lib INSTALLS += target kscope-1.9.4/editor/actions.cpp0000644000175000001440000001126611156714354015637 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "actions.h" namespace KScope { namespace Editor { /** * Class constructor. * Creates the actions. * @param parent Owner object */ Actions::Actions(QObject* parent) : QObject(parent), editor_(NULL) { // Disable all actions when the editor pointer is invalid. editorGroup_ = new QActionGroup(this); editorGroup_->setEnabled(false); connect(this, SIGNAL(editorChanged(bool)), editorGroup_, SLOT(setEnabled(bool))); // Copy selected text. actCopy_ = new QAction(tr("&Copy"), this); actCopy_->setShortcut(QKeySequence("Ctrl+C")); actCopy_->setStatusTip(tr("Copy selected text")); connect(actCopy_, SIGNAL(triggered()), this, SLOT(copy())); editorGroup_->addAction(actCopy_); // Cut selected text. actCut_ = new QAction(tr("Cu&t"), this); actCut_->setShortcut(QKeySequence("Ctrl+X")); actCut_->setStatusTip(tr("Cut selected text")); connect(actCut_, SIGNAL(triggered()), this, SLOT(cut())); editorGroup_->addAction(actCut_); // Patse clipboard contents. actPaste_ = new QAction(tr("&Paste"), this); actPaste_->setShortcut(QKeySequence("Ctrl+V")); actPaste_->setStatusTip(tr("Paste clipboard contents")); connect(actPaste_, SIGNAL(triggered()), this, SLOT(paste())); editorGroup_->addAction(actPaste_); // Undo last action. actUndo_ = new QAction(tr("&Undo"), this); actUndo_->setShortcut(QKeySequence("Ctrl+Z")); actUndo_->setStatusTip(tr("Undo last action")); connect(actUndo_, SIGNAL(triggered()), this, SLOT(undo())); editorGroup_->addAction(actUndo_); // Repeat undone action. actRedo_ = new QAction(tr("&Redo"), this); actRedo_->setShortcut(QKeySequence("Ctrl+Y")); actRedo_->setStatusTip(tr("Repeat undone action")); connect(actRedo_, SIGNAL(triggered()), this, SLOT(redo())); editorGroup_->addAction(actRedo_); // Search text in file. actFind_ = new QAction(tr("&Find..."), this); actFind_->setShortcut(QKeySequence("Ctrl+F")); actFind_->setStatusTip(tr("Search text in file")); connect(actFind_, SIGNAL(triggered()), this, SLOT(find())); editorGroup_->addAction(actFind_); // Repeat last search. actFindNext_ = new QAction(tr("Find &Next"), this); actFindNext_->setShortcut(QKeySequence("F3")); actFindNext_->setStatusTip(tr("Repeat last search")); connect(actFindNext_, SIGNAL(triggered()), this, SLOT(findNext())); editorGroup_->addAction(actFindNext_); // Go to line. actGotoLine_ = new QAction(tr("&Go to Line..."), this); actGotoLine_->setShortcut(QKeySequence("Ctrl+G")); actGotoLine_->setStatusTip(tr("Move cursor to a different line")); connect(actGotoLine_, SIGNAL(triggered()), this, SLOT(gotoLine())); editorGroup_->addAction(actGotoLine_); actBlockBegin_ = new QAction(tr("&Block Beginning"), this); actBlockBegin_->setShortcut(QKeySequence("Ctrl+{")); actBlockBegin_->setStatusTip(tr("Go to the beginning of the current " "block")); connect(actBlockBegin_, SIGNAL(triggered()), this, SLOT(gotoBlockBegin())); editorGroup_->addAction(actBlockBegin_); } /** * Class destructor. */ Actions::~Actions() { } /** * Fills a menu with editor actions. * @param menu A menu to which actions should be added */ void Actions::setupMenu(QMenu* menu) { menu->addAction(actCopy_); menu->addAction(actCut_); menu->addAction(actPaste_); menu->addSeparator(); menu->addAction(actUndo_); menu->addAction(actRedo_); menu->addSeparator(); menu->addAction(actFind_); menu->addAction(actFindNext_); menu->addSeparator(); menu->addAction(actGotoLine_); menu->addAction(actBlockBegin_); } /** * Sets a new managed editor. * @param editor The editor to manage, or NULL if no editor is available */ void Actions::setEditor(Editor* editor) { editor_ = editor; emit editorChanged(editor_ != NULL); } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/lexerstylemodel.cpp0000644000175000001440000005532211156714354017421 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include "lexerstylemodel.h" #include "config.h" namespace KScope { namespace Editor { const QString LexerStyleModel::inheritValue_ = ""; const QString LexerStyleModel::styleMagic_ = "Grqt237gva5FA8A3"; /** * Class constructor. * @param parent Parent object */ LexerStyleModel::LexerStyleModel(const Config::LexerList& lexers, QObject* parent) : QAbstractItemModel(parent), root_(NULL) { // Build the style tree from the list of lexers. // The first object is assumed to be the common defaults lexer. Node* defNode = NULL; foreach (QsciLexer* lexer, lexers) { if (defNode == NULL) { // Create the root node. defNode = createStyleNode(&root_, lexer); } else { // Create the default style node for this lexer. Node* lexNode = createStyleNode(defNode, lexer); // Create per-style nodes for this lexer. for (int i = 0; !lexer->description(i).isEmpty(); i++) { // Skip the default style. if (i == lexer->defaultStyle()) continue; createStyleNode(lexNode, lexer, i); } } } } /** * Class destructor. */ LexerStyleModel::~LexerStyleModel() { deleteStyleNode(root_.child(0)); } /** * Reads style data from a QSettings object * @param settings The object to read from * @param force Trust the given settings file, and try to load styles even * if the magic key is not found * @throw Exception If force is not set, thrown in case the magic key is not * found */ void LexerStyleModel::load(QSettings& settings, bool force) { // Check for a magic key, identifying the settings object as a valid style // scheme. settings.beginGroup("EditorStyles"); if (!force) { if ((settings.status() != QSettings::NoError) || (settings.value("KScopeStyleSchemeMagic", "").toString() != styleMagic_)) { settings.endGroup(); throw new Core::Exception(tr("Not a valid style scheme")); } } // Recursively load styles. loadStyle(settings, root_.child(0)); settings.endGroup(); } /** * Writes style data to a QSettings object * @param settings The object to write to * @param force Ignore errors * @throw Exception */ void LexerStyleModel::store(QSettings& settings, bool force) const { if (!force && (settings.status() != QSettings::NoError)) throw new Core::Exception(tr("Failed to write style scheme")); settings.beginGroup("EditorStyles"); settings.setValue("KScopeStyleSchemeMagic", styleMagic_); storeStyle(settings, root_.child(0)); settings.endGroup(); } /** * Copies style data from another model. * @param model The model to copy from */ void LexerStyleModel::copy(const LexerStyleModel& model) { copyStyle(root_.child(0), model.root_.child(0)); } /** * Uses the data stored in the model to update the style properties of all * managed lexers. * This method should be called after any changes are applied to the model. */ void LexerStyleModel::updateLexers() const { updateLexerStyle(root_.child(0)); } /** * Forces all child styles to inherit the given property. * @param index Corresponds to a property node in the parent style */ void LexerStyleModel::applyInheritance(const QModelIndex& index) { // Ensure the index corresponds to a property node. Node* node = nodeFromIndex(index); if ((node == NULL) || (node->data() == NULL) || (node->data()->type() != PropertyNode)) { return; } // Apply inheritance to child styles. PropertyData* data = static_cast(node->data()); inheritProperty(data->value_, data->styleNode_, data->prop_, true); } /** * Restores the default styles. */ void LexerStyleModel::resetStyles() { resetStyle(root_.child(0)); reset(); } /** * Creates an index. * @param row The row of the index, relative to the parent * @param column The column of the index * @param parent The parent index. * @return The resulting index */ QModelIndex LexerStyleModel::index(int row, int column, const QModelIndex& parent) const { const Node* node = nodeFromIndex(parent); if (node == NULL) return QModelIndex(); // Root nodes do not have data. if (node->data() == NULL) return createIndex(row, column, (void*)node->child(row)); // Property nodes do not have children. if (node->data()->type() == PropertyNode) return QModelIndex(); // For column 2 on a style node, return an index representing the root // property node. if (column == 2) { StyleData* style = static_cast(node->data()); return createIndex(row, column, (void*)&style->propRoot_); } // Return an index representing a child style. return createIndex(row, column, (void*)node->child(row)); } /** * Finds the parent for the given index. * @param index The index for which the parent is needed * @return The parent index */ QModelIndex LexerStyleModel::parent(const QModelIndex& index) const { if (!index.isValid()) return QModelIndex(); const Node* node = nodeFromIndex(index); if (node == NULL) return QModelIndex(); // Handle root nodes. if (node->data() == NULL) return QModelIndex(); // Handle top-level style nodes. if (node->parent() == &root_) return QModelIndex(); return createIndex(node->parent()->index(), 0, node->parent()); } /** * Determines the number of child indices for the given parent. * @param parent The parent index * @return The number of children for the index */ int LexerStyleModel::rowCount(const QModelIndex& parent) const { const Node* node = nodeFromIndex(parent); if (node == NULL) return 0; // Handle root nodes. if (node->data() == NULL) return node->childCount(); // Property nodes have no children. if (node->data()->type() == PropertyNode) return 0; // Column 2 is used for editing properties, so the number of children // is the number of available properties. if (parent.column() == 2) { StyleData* data = static_cast(node->data()); return data->propRoot_.childCount(); } return node->childCount(); } /** * Determines the number of columns in children of the given index. * This number is always 2. * @param parent Ignored * @return The number of columns for children of the index */ int LexerStyleModel::columnCount(const QModelIndex& parent) const { (void)parent; return 2; } /** * Provides the data to display/edit for a given index and role. * @param index The index for which data is requested * @param role The requested role * @return The relevant data */ QVariant LexerStyleModel::data(const QModelIndex& index, int role) const { const Node* node = nodeFromIndex(index); if (node == NULL || node->data() == NULL) return 0; if (node->data()->type() == StyleNode) { // Get the lexer and style ID for this node. StyleData* data = static_cast(node->data()); QsciLexer* lexer = data->lexer_; int style = data->style_; switch (index.column()) { case 0: // Show language name or style name in the first column. if (role == Qt::DisplayRole) { if (style == lexer->defaultStyle()) return lexer->language(); return lexer->description(style); } break; case 1: // Show a formatted text string in the second column, using the // style's properties. return styleData(node, role); } } else { // Get the lexer and style ID for this node. PropertyData* data = static_cast(node->data()); switch (index.column()) { case 0: if (role == Qt::DisplayRole) return propertyName(data->prop_); break; case 1: return propertyData(data, role); } } return QVariant(); } /** * Modifies a style's property. * The method updates the property to which the index corresponds, as well as * the same property for all child styles that inherit this property. * @param index Corresponds to a property node * @param value The new value to set * @param role Must be Qt::EditRole * @return true if the property was updated, false otherwise */ bool LexerStyleModel::setData(const QModelIndex& index, const QVariant& value, int role) { // Can only modify property nodes. Node* node = nodeFromIndex(index); if (!node || !node->data() || !node->data()->type() == PropertyNode) return false; if (role != Qt::EditRole) return false; // Set the property's value. PropertyData* data = static_cast(node->data()); Node* styleNode = data->styleNode_; setProperty(value, styleNode, data->prop_, QVariant()); // Update changes. emit dataChanged(index, index); QModelIndex styleIndex = createIndex(styleNode->index(), 1, styleNode); emit dataChanged(styleIndex, styleIndex); // Apply property to inheriting styles. inheritProperty(value, styleNode, data->prop_, false); return true; } Qt::ItemFlags LexerStyleModel::flags(const QModelIndex& index) const { const Node* node = nodeFromIndex(index); if (!node || !node->data()) return Qt::NoItemFlags; Qt::ItemFlags flags = Qt::NoItemFlags; switch (node->data()->type()) { case StyleNode: flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; break; case PropertyNode: flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() == 1) flags |= Qt::ItemIsEditable; break; } return flags; } /** * Allocates a new node for the given lexer and style. * Always use this method to create a new node, to ensure that the proeprties * for this style are also created. * @param parent Pointer to the parent node * @param lexer The lexer to use * @param style The style ID * @return A pointer to the new node */ LexerStyleModel::Node* LexerStyleModel::createStyleNode(Node* parent, QsciLexer* lexer, int style) { // Create the node. StyleData* data = new StyleData(lexer, style); Node* node = parent->addChild(data); // Create style properties. for (uint i = 0; i != _LastProperty; i++) { PropertyData* prop = new PropertyData(static_cast(i)); prop->styleNode_ = node; data->propRoot_.addChild(prop); } return node; } /** * Recursively deteles style nodes. * @param node The node to delete */ void LexerStyleModel::deleteStyleNode(Node* node) { // Recursive call first. for (int i = 0; i < node->childCount(); i++) deleteStyleNode(node->child(i)); // Delete all property data. StyleData* data = static_cast(node->data()); for (int i = 0; i < data->propRoot_.childCount(); i++) { Node* child = data->propRoot_.child(i); delete child->data(); data->propRoot_.clear(); } // Delete the node's data. delete data; } /** * Reads style data from a QSettings object for the given node and all its * children. * @param settings The QSettings object to read from * @param node The style node */ void LexerStyleModel::loadStyle(QSettings& settings, Node* node) { // Get the lexer and style ID from the node data. StyleData* data = static_cast(node->data()); QsciLexer* lexer = data->lexer_; int style = data->style_; // Create a key template for the settings object, of the form // LEXER\STYLE\%1, where %1 will be replaced by the property name. QString key = QString("Style/%1/%2/%3").arg(lexer->lexer()).arg(style); // Get the properties. for (uint i = 0; i != _LastProperty; i++) { StyleProperty prop = static_cast(i); setProperty(settings.value(key.arg(propertyKey(prop))), node, prop, propertyDefaultValue(lexer, style, prop)); } // Recursive call. for (int i = 0; i < node->childCount(); i++) loadStyle(settings, node->child(i)); } /** * Writes style data to a QSettings object for the given node and all its * children. * @param settings The QSettings object to write to * @param node The style node */ void LexerStyleModel::storeStyle(QSettings& settings, const Node* node) const { // Get the lexer and style ID from the node data. StyleData* data = static_cast(node->data()); QsciLexer* lexer = data->lexer_; int style = data->style_; // Create a key template for the settings object, of the form // LEXER\STYLE\%1, where %1 will be replaced by the property name. QString key = QString("Style/%1/%2/%3").arg(lexer->lexer()).arg(style); // Get the properties. for (uint i = 0; i != _LastProperty; i++) { StyleProperty prop = static_cast(i); PropertyData* propData = propertyDataFromNode(node, prop); QVariant value = propData->inherited_ ? inheritValue_ : propData->value_; settings.setValue(key.arg(propertyKey(prop)), value); } // Recursive call. for (int i = 0; i < node->childCount(); i++) storeStyle(settings, node->child(i)); } /** * Recursively copies style node data from another model. * @param destNode The node to copy to * @param srcNode The node to copy from */ void LexerStyleModel::copyStyle(Node* destNode, const Node* srcNode) { StyleData* destData = static_cast(destNode->data()); StyleData* srcData = static_cast(srcNode->data()); // Copy the style data. destData->lexer_ = srcData->lexer_; destData->style_ = srcData->style_; // Copy properties. for (uint i = 0; i != _LastProperty; i++) { StyleProperty prop = static_cast(i); PropertyData* destProp = propertyDataFromNode(destNode, prop); PropertyData* srcProp = propertyDataFromNode(srcNode, prop); destProp->value_ = srcProp->value_; destProp->inherited_ = srcProp->inherited_; } // Recursive call. for (int i = 0; i < destNode->childCount(); i++) copyStyle(destNode->child(i), srcNode->child(i)); } /** * Recursively updates lexer style properties, using the data stored in the * model. * @param node The style node holding the lexer to update */ void LexerStyleModel::updateLexerStyle(const Node* node) const { StyleData* data = static_cast(node->data()); QsciLexer* lexer = data->lexer_; int style = data->style_; // Update lexer properties. QFont font = propertyDataFromNode(node, Font)->value_.value(); lexer->setFont(font, style); QColor foreground = propertyDataFromNode(node, Foreground)->value_.value(); lexer->setColor(foreground, style); QColor background = propertyDataFromNode(node, Background)->value_.value(); lexer->setPaper(background, style); // This is really nasty, but Scintilla leaves us no choice... // The EOL Fill flag needs to be set in order for whitespace past the end // of line to be drawn in the desired background colour. We apply this flag // to the default style, as well as any styles that have the same background // colour as the default. if ((style == lexer->defaultStyle()) || (lexer->paper(style) == lexer->paper(lexer->defaultStyle()))) { lexer->setEolFill(true, style); } // Recursive call. for (int i = 0; i < node->childCount(); i++) updateLexerStyle(node->child(i)); } /** * Resets the style to use the default properties. * @param node The style node to reset */ void LexerStyleModel::resetStyle(Node* node) { StyleData* data = static_cast(node->data()); QsciLexer* lexer = data->lexer_; int style = data->style_; for (uint i = 0; i != _LastProperty; i++) { StyleProperty prop = static_cast(i); setProperty(QVariant(), node, prop, propertyDefaultValue(lexer, style, prop)); } // Recursive call. for (int i = 0; i < node->childCount(); i++) resetStyle(node->child(i)); } /** * Assigns a value to a property. * The val parameter that is passed to this method can have one of three types * of values: * 1. A value that matches to the type of the property, * 2. The special string "", * 3. An invalid QVariant. * In the first case, the given value is set to the property. In the second, the * property value is set to that of the matching property as defined by the * parent style. * The third case happens when a property value is not defined (e.g., when * reading from an initial settings file). The property is set to the lexer's * value for that style, as passed in the defVal parameter. The method then * guesses whether the value is inherited, by comparing the value with that * of the parent style. This should give a good out-of-the-box default * behaviour. * @param val The value to assign * @param node The style node that owns the property * @param prop Property ID * @param defVal A default value to use */ void LexerStyleModel::setProperty(const QVariant& val, Node* node, StyleProperty prop, const QVariant& defVal) { PropertyData* data = propertyDataFromNode(node, prop); // Assign the value if its type matches the property type. if (val.type() == propertyType(prop)) { data->value_ = val; data->inherited_ = false; return; } // The root style cannot inherit values. // Use the default value, if it was properly defined. Otherwise, leave the // current value. if (node->parent() == &root_) { if (defVal.type() == propertyType(prop)) data->value_ = defVal; data->inherited_ = false; return; } // Determine whether the value should be inherited. if (!isInheritValue(val)) { // No value was found in the settings object, and the property is // not marked as inherited. // Make an educated guess on whether the property should be // inherited, by checking if the parent value is the same as the // default one. if ((defVal.type() == propertyType(prop)) && (propertyDataFromNode(node->parent(), prop)->value_ != defVal)) { // Parent value differs, use the default one. data->value_ = defVal; data->inherited_ = false; return; } } // The value should be inherited. // Get the parent style's value for this property. data->value_ = propertyDataFromNode(node->parent(), prop)->value_; data->inherited_ = true; } /** * Recursively applies a property to all inheriting styles. * @param val The new property value * @param node The parent style node * @param prop The property to set * @param force true to apply always inheritance, false to apply only if the * property is currently marked as inherited */ void LexerStyleModel::inheritProperty(const QVariant& val, Node* node, StyleProperty prop, bool force) { PropertyData* data = propertyDataFromNode(node, prop); for (int i = 0; i < node->childCount(); i++) { // Get the child node information. Node* child = node->child(i); PropertyData* childData = propertyDataFromNode(child, prop); // Force inheritance, if requested. if (force) childData->inherited_ = true; // Check if this property is inherited by the child. if (childData->inherited_) { // Set the new value. childData->value_ = data->value_; // Notify views of the change. QModelIndex index = createIndex(i, 1, (void*)child); emit dataChanged(index, index); // Recursive application. inheritProperty(val, child, prop, force); } } } /** * Creates a string with the style's font and colours to be displayed for the * second column of a style item. * @param node The style node * @param role The role to use * @return The data for the given style and role */ QVariant LexerStyleModel::styleData(const Node* node, int role) const { switch (role) { case Qt::DisplayRole: return QString("Sample Text"); case Qt::FontRole: return propertyDataFromNode(node, Font)->value_; case Qt::ForegroundRole: return propertyDataFromNode(node, Foreground)->value_; case Qt::BackgroundRole: return propertyDataFromNode(node, Background)->value_; default: ; } return QVariant(); } /** * @param prop Property value * @return A display name for this property */ QString LexerStyleModel::propertyName(StyleProperty prop) const { switch (prop) { case Font: return tr("Font"); case Foreground: return tr("Text Colour"); case Background: return tr("Background Colour"); default: // Must not get here. Q_ASSERT(false); } return QString(); } /** * @param prop Property value * @return The QVariant type that is used to hold values for this property */ QVariant::Type LexerStyleModel::propertyType(StyleProperty prop) const { switch (prop) { case Font: return QVariant::Font; case Foreground: return QVariant::Color; case Background: return QVariant::Color; default: // Must not get here. Q_ASSERT(false); } return QVariant::Invalid; } /** * @param data Property data * @param role The role to use * @return The value to return for this property */ QVariant LexerStyleModel::propertyData(PropertyData* data, int role) const { switch (role) { case Qt::DisplayRole: if (data->inherited_) return tr("Inherit"); if (propertyType(data->prop_) == QVariant::Font) return data->value_; break; case Qt::DecorationRole: if ((!data->inherited_) && (propertyType(data->prop_) == QVariant::Color)) { return data->value_; } break; case Qt::EditRole: return data->value_; } return QVariant(); } /** * @param prop Property value * @return The key used to store this property in a QSettings object */ QString LexerStyleModel::propertyKey(StyleProperty prop) const { switch (prop) { case Font: return "Font"; case Foreground: return "Foreground"; case Background: return "Background"; default: // Must not get here. Q_ASSERT(false); } return QString(); } /** * Determines the default value for a given style's property. * @param lexer The lexer to which the style belong * @param style The style to use * @param prop The property for which the value is requested * @return The default value of the property for this lexer and style */ QVariant LexerStyleModel::propertyDefaultValue(QsciLexer* lexer, int style, StyleProperty prop) const { switch (prop) { case Font: return lexer->defaultFont(style); case Foreground: return lexer->defaultColor(style); case Background: return lexer->defaultPaper(style); default: // Must not get here. Q_ASSERT(false); } return QVariant(); } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/configdialog.cpp0000644000175000001440000001551511156714354016625 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include "configdialog.h" #include "lexerstylemodel.h" #include "lexerstyledelegate.h" namespace KScope { namespace Editor { /** * Class constructor. * @param config Holds the configuration parameters to display by default * @param parent Parent widget */ ConfigDialog::ConfigDialog(const Config& config, QWidget* parent) : QDialog(parent), Ui::ConfigDialog() { setupUi(this); // Update the controls to reflect the given configuration. hlCurLineCheck_->setChecked(config.hlCurLine_); visibleWSpaceCheck_->setChecked(config.visibleWSpace_); marginLineNumbersCheck_->setChecked(config.marginLineNumbers_); eolMarkerCheck_->setChecked(config.eolMarkerColumn_ > 0); eolMarkerSpin_->setValue(config.eolMarkerColumn_); indentTabsCheck_->setChecked(config.indentTabs_); tabWidthSpin_->setValue(config.tabWidth_); // We use a copy of the style model managed by the Config object, so that // changes to the model do not persist in case the dialogue is cancelled. styleModel_ = new LexerStyleModel(config.lexers_, this); styleModel_->copy(*config.styleModel_); connect(resetButton_, SIGNAL(clicked()), styleModel_, SLOT(resetStyles())); // Prepare the style editor. styleView_->setModel(styleModel_); propView_->setModel(styleModel_); connect(styleView_->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(editStyle(const QModelIndex&))); // Create the delegate for editing properties. LexerStyleDelegate* delegate = new LexerStyleDelegate(this); connect(delegate, SIGNAL(editProperty(const QModelIndex&, const QVariant&)), this, SLOT(editProperty(const QModelIndex&, const QVariant&))); propView_->setItemDelegate(delegate); // Select the top index, so that the property view shows its properties, // rather than a tree of styles. QModelIndex index = styleModel_->index(0, 0); styleView_->setCurrentIndex(index); // Populate language combo-boxes. lexerModel_ = new QStandardItemModel(this); int row = 0; foreach (QsciLexer* lexer, config.lexers_) { QStandardItem* item = new QStandardItem(lexer->language()); item->setData(QVariant::fromValue((void*)lexer)); lexerModel_->setItem(row++, 0, item); } indentLanguageCombo_->setModel(lexerModel_); // Set up the Vi mode combo-box. viModeCombo_->insertItem(0, tr("Disabled"), ViScintilla::Disabled); viModeCombo_->insertItem(1, tr("Insert"), ViScintilla::InsertMode); viModeCombo_->insertItem(2, tr("Normal"), ViScintilla::NormalMode); int modeIndex = viModeCombo_->findData(config.viDefaultMode_); viModeCombo_->setCurrentIndex(modeIndex); } /** * Class destructor. */ ConfigDialog::~ConfigDialog() { } /** * Copies the parameters in the dialogue to the given configuration object. * @param config The configuration object */ void ConfigDialog::getConfig(Config& config) { config.hlCurLine_ = hlCurLineCheck_->isChecked(); config.visibleWSpace_ = visibleWSpaceCheck_->isChecked(); config.marginLineNumbers_ = marginLineNumbersCheck_->isChecked(); config.eolMarkerColumn_ = eolMarkerCheck_->isChecked() ? eolMarkerSpin_->value() : 0; config.indentTabs_ = indentTabsCheck_->isChecked(); config.tabWidth_ = tabWidthSpin_->value(); int modeIndex = viModeCombo_->currentIndex(); config.viDefaultMode_ = static_cast (viModeCombo_->itemData(modeIndex).toUInt()); config.styleModel_->copy(*styleModel_); config.styleModel_->updateLexers(); } void ConfigDialog::indentLanguageChanged(int id) { // TODO: Implement. (void)id; } /** * Changes all styles to use their default values. * If the "Use default font" check-box is checked, then the font property is * ignored (i.e., not reset). */ void ConfigDialog::resetStyles() { LexerStyleModel* styleModel = static_cast(styleView_->model()); styleModel->resetStyles(); } /** * Prompts the user for a settings file containing a style scheme, and loads * the styles into the model. */ void ConfigDialog::importStyles() { // Prompt for a file. QString file = QFileDialog::getOpenFileName(this, tr("Import Styles")); if (file.isEmpty()) return; // Load the styles. QSettings settings(file, QSettings::IniFormat); try { styleModel_->load(settings, false); } catch (Core::Exception* e) { e->showMessage(); delete e; } } /** * Allows the user to save the current style scheme to an external file. */ void ConfigDialog::exportStyles() { // Prompt for a file. QString file = QFileDialog::getSaveFileName(this, tr("Export Styles")); if (file.isEmpty()) return; // Store the styles. QSettings settings(file, QSettings::IniFormat); try { styleModel_->store(settings, false); } catch (Core::Exception* e) { e->showMessage(); delete e; } } void ConfigDialog::editStyle(const QModelIndex& index) { QModelIndex propRoot = index.child(0, 2); propView_->setRootIndex(propRoot); } void ConfigDialog::editProperty(const QModelIndex& index, const QVariant& currentValue) { QVariant newValue; switch (currentValue.type()) { case QVariant::Font: { bool ok; QFont font = QFontDialog::getFont(&ok, currentValue.value(), this); if (!ok) return; newValue.setValue(font); } break; case QVariant::Color: { QColor clr = QColorDialog::getColor(currentValue.value(), this); if (!clr.isValid()) return; newValue.setValue(clr); } break; default: Q_ASSERT(false); return; } LexerStyleModel* model = static_cast(styleView_->model()); model->setData(index, newValue, Qt::EditRole); } void ConfigDialog::applyInheritance() { QModelIndex index = propView_->selectionModel()->currentIndex(); if (index.isValid()) styleModel_->applyInheritance(index); } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/viscintilla.h0000644000175000001440000001477011156714354016170 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_VISCINTILLA_H__ #define __EDITOR_VISCINTILLA_H__ #include #include #include namespace KScope { namespace Editor { /** * A sequence of characters with read-only sharing. * Used to pass around the Vi command sequence without creating unnecessary * copies. * @author Elad Lahav */ class CharSequence { public: /** * Default constructor. * Creates the sequence. */ CharSequence() : isCopy_(false), first_(0), last_(-1) { buffer_ = new QList(); } /** * Copy constructor. * Creates a sub-sequence that references the same buffer as the one held * by the source sequence. * @param source The source sequence * @param first The beginning of the sub-sequence (relative to the source) * @param last The end of the sub-sequence (relative to the source) */ CharSequence(const CharSequence& source, int first, int last) : buffer_(source.buffer_), isCopy_(true) { if (first >= 0) first_ = source.first_ + first; else first_ = source.last_ + first; if (last > 0) last_ = source.first_ + last; else last_ = source.last_ + last; } /** * Class destructor. * Destroys only the main copy of the buffer. */ ~CharSequence() { if (!isCopy_) delete buffer_; } /** * Adds a character to the sequence. * Can only be used with the master copy. * @param c The character to add. */ void append(char c) { if (!isCopy_) { buffer_->append(c); last_++; } } /** * Removes all characters from the sequence. * Can only be used with the master copy. */ void clear() { first_ = 0; last_ = -1; if (!isCopy_) buffer_->clear(); } /** * @return true if the sequence is empty, false otherwise */ bool isEmpty() const { return first_ > last_; } /** * @return The number of characters in this sequence */ int length() const { return last_ - first_ + 1; } /** * Converts the sequence into a number. * @param ok If not-NULL, used to return a value indicating the success of * the conversion * @return The numeric value of the sequence, 0 if conversion failed */ uint toUInt(bool* ok = NULL) const { uint result = 0; for (int i = first_; i <= last_; i++) { char c = (*buffer_)[i]; if (c < '0' || c > '9') { if (ok) *ok = false; return 0; } result = (result * 10) + (c - '0'); } if (ok) *ok = true; return result; } private: /** * A pointer to the master copy of the buffer. */ QList* buffer_; /** * Whether this sequence is a copy of the master sequence. */ bool isCopy_; /** * The index of the first character in this sub-sequence. */ int first_; /** * The index of the last character in this sub-sequence. */ int last_; }; class ViScintilla; /** * Used to process a Vi command. * Each command is associated with the character that invokes it. */ struct ViCommand { /** * Possible results for processKey(). */ enum ProcessResult { /** * A multi-character command is in progress. */ Continue, /** * The command has finished. */ Done, /** * The command has finished, and the editor should exit Vi normal mode. */ Exit, /** * Key is not recognised by this command. */ NotHandled }; /** * Handles a key press event. * @param key The pressed key, translated into an ASCII code * @param editor The editor to manipulate * @param seq The current command character sequence * @return Result code (@see ProcessResult) */ virtual ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) = 0; }; /** * An implementation of a Vi-style commands on top of Scintilla. * @author Elad Lahav */ class ViScintilla : public QsciScintilla { Q_OBJECT public: ViScintilla(QWidget*); ~ViScintilla(); /** * Editing modes. */ enum EditMode { /** Vi compatibility is disabled. */ Disabled, /** Scintilla's default. */ InsertMode, /** Vi normal mode. */ NormalMode, /** Vi visual mode. */ VisualMode, }; void setEditMode(EditMode mode); void nextWord(int, int, int*, int*); /** * @return The current edit mode */ EditMode editMode() const { return mode_; } const CharSequence& cmdSequence() const { return cmdSequence_; } signals: /** * Emitted when the editing mode changes. * @param mode The new mode */ void editModeChanged(Editor::ViScintilla::EditMode mode); /** * Sends a message to be displayed by the application. * @param msg The message to display * @param msTimeOut How long to display the message, in milliseconds */ void message(const QString& msg, int msTimeOut); protected: /** * The current editing mode. */ EditMode mode_; /** * The current command, based on the first key in the sequence, NULL if no * command is active. */ ViCommand* curCommand_; /** * The current key sequence. */ CharSequence cmdSequence_; /** * A display version of the command sequence. */ QString cmdString_; void keyPressEvent(QKeyEvent*); private: /** * Maps keys to lists of commands. * @author Elad Lahav */ class CommandMap { public: CommandMap(); ~CommandMap(); ViCommand* command(char c); private: /** * The map of characters to commands. */ ViCommand* cmdMap_[0x100]; /** * A list of all commands, used by the destructor. */ QList cmdList_; }; /** * A copy of the command map shared by all ViScintilla objects. */ static CommandMap commandMap_; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_VISCINTILLA_H__ kscope-1.9.4/editor/fileiothread.h0000644000175000001440000000340411156714354016276 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_FILEIOTHREAD_H__ #define __EDITOR_FILEIOTHREAD_H__ #include #include #include namespace KScope { namespace Editor { /** * Thread-based asynchronous file loading/storing. * @author Elad Lahav */ class FileIoThread : public QThread { Q_OBJECT public: FileIoThread(QObject* parent) : QThread(parent) {} bool load(const QString& path) { file_.setFileName(path); if (!file_.open(QIODevice::ReadOnly | QIODevice::Text)) return false; start(); return true; } virtual void run() { QTextStream strm(&file_); QString text; text = strm.readAll(); file_.close(); emit done(text); } signals: void done(const QString& text); private: QFile file_; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_FILEIOTHREAD_H__ kscope-1.9.4/editor/lexerstyledelegate.h0000644000175000001440000000710611156714354017535 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_LEXERSTYLEDELEGATE_H__ #define __EDITOR_LEXERSTYLEDELEGATE_H__ #include #include #include #include "lexerstylemodel.h" namespace KScope { namespace Editor { class StyleMenu : public QComboBox { Q_OBJECT public: StyleMenu(QWidget* parent) : QComboBox(parent) { connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(notifyOnItemSelection())); insertItem(0, tr("" item. if (!var.isValid()) return; // The "Inherit" item, adjust the model. if (LexerStyleModel::isInheritValue(var)) { model->setData(index, var, Qt::EditRole); return; } // The "Custom..." item, signal the view to show an editor dialogue. emit editProperty(index, var); } void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { (void)index; editor->setGeometry(option.rect); } signals: void editProperty(const QModelIndex&, const QVariant&) const; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_LEXERSTYLEDELEGATE_H__ kscope-1.9.4/editor/lexerstylemodel.h0000644000175000001440000002065711156714354017071 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_LEXERSTYLEMODEL_H__ #define __EDITOR_LEXERSTYLEMODEL_H__ #include #include #include #include #include "config.h" namespace KScope { namespace Editor { /** * A model for displaying/editing lexer styles. * QScintilla uses QsciLexer-derived objects for drawing text. Each object * maintains a list of styles corresponding to syntactic entities in a * programming language. Unfortunately, the styles are not hierarchical, making * it quite difficult to express default values for certain properties (e.g., * use a single font for all styles, except for comments). * This model attempts to overcome the limitations of QScintilla's style * management. It keeps styles as a tree, using the following levels: * (1) Common default style * (2) Per-language default style * (3) Syntactic styles * The root item, in level (1), corresponds to the default style of the common * lexer (@see CommonLexer). Each item in level (2) represents a lexer, and * manages the style marked as default for that lexer. Items in level (3) * correspond to all other (i.e., non-default) styles in a lexer. * Each style provides a set of properties that can be configured separately * (font, foreground colour, background colour). Additionally, each property can * be set to inherit the value of its parent style. * The model exposes two columns to views, with data for the first column * providing the name of the style, and the second providing a sample text * string that is formatted to use the styles properties. Additionally, a hidden * third column is used to expose another layer of the model, used for * manipulating properties. Thus, each model index that corresponds to a style * has two sets of children: its sub-styles, as described above, and its * properties. To access the properties, call index(0, 2, parent), where parent * is an index corresponding to a style. This will return a root index for * the set of properties. Using this index as a root of a tree view results in * a property editor. * Note that The model maintains style configuration separately from the actual * lexers, which are held by the editor Config object. Style configuration is * applied to the model directly. These changes can then be used to rebuild the * lexers. * @author Elad Lahav */ class LexerStyleModel : public QAbstractItemModel { Q_OBJECT public: LexerStyleModel(const Config::LexerList&, QObject* parent = NULL); ~LexerStyleModel(); void load(QSettings&, bool); void store(QSettings&, bool) const; void copy(const LexerStyleModel&); void updateLexers() const; void applyInheritance(const QModelIndex&); // QAbstractItemModel implementation. QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const; QModelIndex parent(const QModelIndex&) const; int rowCount(const QModelIndex& parent = QModelIndex()) const; int columnCount(const QModelIndex& parent = QModelIndex()) const; QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const; bool setData(const QModelIndex&, const QVariant&, int role); Qt::ItemFlags flags(const QModelIndex&) const; static QVariant inheritValue() { return inheritValue_; } static bool isInheritValue(const QVariant& var) { return var.toString() == inheritValue_; } public slots: void resetStyles(); private: enum NodeType { StyleNode, PropertyNode }; enum StyleProperty { Font = 0, Foreground, Background, _LastProperty }; struct NodeData { virtual NodeType type() const = 0; }; /** * A node in the style tree. */ typedef Core::TreeItem Node; /** * Defines a property node. * Property nodes are the children of a special property root node, which * is embedded in every style node. */ struct PropertyData : public NodeData { /** * Struct constructor. * @param prop The property represented by this node */ PropertyData(StyleProperty prop = _LastProperty) : prop_(prop), value_(), inherited_(false) {} /** * @return The type of this node */ NodeType type() const { return PropertyNode; } /** * The property ID. */ StyleProperty prop_; /** * The current property value. * This is always set to the actual value to use, regardless of whether * the property is inherited or not. */ QVariant value_; /** * Whether the property is inherited. */ bool inherited_; /** * The style node that owns this property. */ Node* styleNode_; }; /** * Defines a node in the tree of styles. */ struct StyleData : public NodeData { /** * Struct constructor. * @param lexer The lexer object to use * @param style The style ID, -1 to use the default style for this * lexer */ StyleData(QsciLexer* lexer = NULL, int style = -1) : lexer_(lexer), propRoot_(NULL) { // Determine the style ID. if ((lexer_ != NULL) && (style == -1)) style_ = lexer->defaultStyle(); else style_ = style; } /** * @return The type of this node */ NodeType type() const { return StyleNode; } /** * The lexer with which this style is associated. */ QsciLexer* lexer_; /** * The ID of the style managed by this node. */ int style_; /** * The root of a sub-tree holding property information. */ Node propRoot_; }; /** * The root of the style tree. * Note that this is a fake node, whose only child is the common default * style (i.e., the top-level style). */ Node root_; /** * Converts a model index into a style tree node. * @param index The index to convert from * @return The resulting node (may be NULL) */ Node* nodeFromIndex(const QModelIndex& index) { if (!index.isValid()) return &root_; return static_cast(index.internalPointer()); } /** * Converts a model index into a style tree node (const version). * @param index The index to convert from * @return The resulting node (may be NULL) */ const Node* nodeFromIndex(const QModelIndex& index) const { if (!index.isValid()) return &root_; return static_cast(index.internalPointer()); } static inline PropertyData* propertyDataFromNode(const Node* node, StyleProperty prop) { StyleData* style = static_cast(node->data()); Core::TreeItem* propNode = static_cast*> (style->propRoot_.child(prop)); return static_cast(propNode->data()); } /** * Identifies the special property value, marking a property as inherited. */ static const QString inheritValue_; /** * Used to verify that a settings object contains a valid style scheme. */ static const QString styleMagic_; Node* createStyleNode(Node*, QsciLexer*, int style = -1); void deleteStyleNode(Node*); void loadStyle(QSettings&, Node*); void storeStyle(QSettings&, const Node*) const; void copyStyle(Node*, const Node*); void updateLexerStyle(const Node*) const; void resetStyle(Node*); void setProperty(const QVariant&, Node*, StyleProperty, const QVariant&); void inheritProperty(const QVariant&, Node*, StyleProperty, bool); QVariant styleData(const Node*, int) const; QString propertyName(StyleProperty) const; QVariant::Type propertyType(StyleProperty) const; QVariant propertyData(PropertyData*, int role) const; QString propertyKey(StyleProperty) const; QVariant propertyDefaultValue(QsciLexer*, int, StyleProperty) const; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_LEXERSTYLEMODEL_H__ kscope-1.9.4/editor/editor.cpp0000644000175000001440000002443411156714354015466 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include #include #include #include #include #include "editor.h" #include "fileiothread.h" #include "findtextdialog.h" namespace KScope { namespace Editor { /** * Class constructor. * @param parent Owner object */ Editor::Editor(QWidget* parent) : ViScintilla(parent), newFileIndex_(0), isLoading_(false), onLoadLine_(0), onLoadColumn_(0), onLoadFocus_(false) { } /** * Class destructor. */ Editor::~Editor() { } /** * Asynchronously loads the contents of the given file into the editor. * Launches a thread that reads the file contents. When done, the thread signals * the editor with the read text. * During the loading process, the editor widget is disabled. Any calls to * setCursorPosition() or setFocus() are delayed until loading finishes. * @param path The path of the file to load * @param lexer Text formatter * @return true if the loading process started successfully, false otherwise */ bool Editor::load(const QString& path, QsciLexer* lexer) { // Indicate that loading is in progress. isLoading_ = true; setEnabled(false); setText(tr("Loading...")); setLexer(lexer); // Create and start the loading thread. FileIoThread* thread = new FileIoThread(this); connect(thread, SIGNAL(done(const QString&)), this, SLOT(loadDone(const QString&))); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); if (!thread->load(path)) { setText(tr("Loading failed")); return false; } // Store the path. path_ = path; return true; } /** * Writes the contents of the editor back to the file. * @note The current implementation is synchronous, which may cause KScope to * hang if the saving process takes too long (e.g., for NFS-mounted * files). This should be fixed at some point. * @return true if successful, false otherwise */ bool Editor::save() { // Nothing to do if the contents did not change since the last save. if (!isModified()) return true; // Prompt for a file name if the editor is holding a new file. QString path = path_; if (path.isEmpty()) { path = QFileDialog::getSaveFileName(this, tr("Save New File")); if (path.isEmpty()) return false; } // TODO: Provide an asynchronous implementation. QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QString msg = tr("Failed to save '%1'").arg(path_); QMessageBox::critical(this, tr("File Error"), msg); return false; } // Save the file's contents. QTextStream strm(&file); strm << text(); // Notify of a change in the file path, if necessary. if (path != path_) { QString oldTitle = title(); path_ = path; emit titleChanged(oldTitle, title()); } return true; } /** * Determines whether the editor can be safely closed. * This is the case if the contents are not modified, the user saves the changes * or the user decides that the contents should not be saved. * @return true if the editor can be closed, false otherwise */ bool Editor::canClose() { if (isModified()) { // Prompt the user for unsaved changes. QString msg = tr("The file '%1' was modified.\n" "Would you like to save it?") .arg(path_); QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel; switch (QMessageBox::question(0, tr("Unsaved Changes"), msg, buttons)) { case QMessageBox::Yes: // Save the contents of the editor. if (!save()) return false; break; case QMessageBox::No: // Ignore changes. setModified(false); break; default: // Stop the close operation. return false; } } return true; } /** * Moves the cursor to the requested position in the document. * This function translates 1-based line and column indexes into the 0-based * values used by Scintilla. We use 0 values as "don't cares", that do not * change the current value of the respective dimension (line or column). * @param line 1-based line number, 0 to keep the current line * @param column 1-based column number, 0 to keep the current column */ void Editor::moveCursor(uint line, uint column) { // Wait for file loading to complete before setting a new position. if (isLoading_) { if (line) onLoadLine_ = line; if (column) onLoadColumn_ = column; return; } // Get current values. int curLine, curColumn; getCursorPosition(&curLine, &curColumn); // Determine the new line position. if (line == 0) line = curLine; else line--; // Determine the new column position. if (column == 0) column = curColumn; else column--; // Set the new cursor position. ViScintilla::setCursorPosition(line, column); } /** * Returns a symbol for automatic selection. * If any text is selected in the editor, it is returned. Otherwise, the method * returns the word on which the cursor is currently positioned. * @return The current text */ QString Editor::currentSymbol() const { // Return any selected text. // TODO: Should we test for a valid symbol here to? if (hasSelectedText()) return QsciScintilla::selectedText(); // No selected text. // Get the boundaries of the word from the current cursor position. long pos, start, end; pos = SendScintilla(SCI_GETCURRENTPOS); start = SendScintilla(SCI_WORDSTARTPOSITION, pos, 0L); end = SendScintilla(SCI_WORDENDPOSITION, pos, 0L); // Return an empty string if no word is found. if (start >= end) return QString(); // Extract the word's text using its position boundaries. QByteArray curText; curText.resize(end - start ); SendScintilla(SCI_GETTEXTRANGE, start, end, curText.data()); // NOTE: Scintilla's definition of a "word" does not correspond to a // "symbol". Make sure the result contains only alpha-numeric characters // or an underscore. QString symbol(curText); if (!QRegExp("\\w+").exactMatch(symbol)) return QString(); return symbol; } /** * Sets the input focus to the editor. * If the editor is currently loading a file, the focus will be set when the * process finishes. */ void Editor::setFocus() { if (isLoading_) onLoadFocus_ = true; else QsciScintilla::setFocus(); } /** * Fills a Location structure with information on the current file name, line * and column. * @param loc The structure to fill */ void Editor::getCurrentLocation(Core::Location& loc) { int line, col; // Get the current cursor position. getCursorPosition(&line, &col); // Fill the structure. loc.file_ = path_; loc.line_ = line + 1; loc.column_ = col + 1; loc.text_ = text(line).trimmed(); } /** * Generates a unique title for this editor. * The title is used both to identify the editor in the file map managed by the * container, as well as for display purposes. * @return The editor's title */ QString Editor::title() const { if (path_.isEmpty()) return tr("Untitled %1").arg(newFileIndex_); return path_; } /** * Searches for text inside the document. * Prompts the user for the text to find. */ void Editor::search() { // Prompt for text to find. QString pattern = currentSymbol(); SearchOptions options; if (FindTextDialog::promptPattern(pattern, options, this) != QDialog::Accepted) { return; } // Find the first occurrence of the searched text. if (!QsciScintilla::findFirst(pattern, options.regExp_, options.caseSensitive_, options.wholeWordsOnly_, options.wrap_, !options.backward_)) { QString msg = tr("'%1' could not be found in the document") .arg(pattern); QMessageBox::warning(this, tr("Pattern not found"), msg); } } /** * Searches for the next occurrence of the previously-selected text inside the * document. */ void Editor::searchNext() { if (!QsciScintilla::findNext()) { QString msg = tr("No more matches."); QMessageBox::warning(this, tr("Pattern not found"), msg); } } /** * Prompts the user for a line number and moves the cursor to the selected line. */ void Editor::gotoLine() { // Get the current line number. int line, column; getCursorPosition(&line, &column); // Prompt for a new line number. bool ok; line = QInputDialog::getInteger(this, tr("Enter Line Number"), tr("Line"), line + 1, 1, lines(), 1, &ok); if (ok) setCursorPosition(line - 1, 0); } /** * Moves the cursor to the beginning of the current block. */ void Editor::gotoBlockBegin() { int line, column, newline; getCursorPosition(&line, &column); newline = SendScintilla(QsciScintillaBase::SCI_GETFOLDPARENT, line); setCursorPosition(newline, 0); } /** * Called before the editor window is closed. * Checks whether the editor can be closed, and if so, accepts the event. * @param event The close event */ void Editor::closeEvent(QCloseEvent* event) { if (canClose()) { emit closed(title()); event->accept(); } else { event->ignore(); } } /** * Called when the thread loading the file for the editor terminates. * Invokes any methods that were deferred while the file was loading. * @param text The contents of the file */ void Editor::loadDone(const QString& text) { setText(text); setModified(false); isLoading_ = false; moveCursor(onLoadLine_, onLoadColumn_); setEnabled(true); if (onLoadFocus_) { setFocus(); onLoadFocus_ = false; } } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/viscintilla.cpp0000644000175000001440000004266511156714354016527 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "viscintilla.h" namespace KScope { namespace QtKey { /** * Defines a set of functions for comparing two keys. * @author Elad Lahav */ template struct Compare { static const bool gt_ = (Key1 > Key2); static const bool lt_ = (Key1 < Key2); static const bool ge_ = (Key1 >= Key2); static const bool le_ = (Key1 <= Key2); }; /** * Determines whether the template parameter is a letter key. */ template struct IsLetter { static const bool result_ = (Compare::ge_) && (Compare::le_); }; /** * Determines whether the template parameter is a digit key. * @author Elad Lahav */ template struct IsDigit { static const bool result_ = (Compare::ge_) && (Compare::le_); }; /** * Provides compile- and run-time functions for translating a key into an ASCII * character. * @author Elad Lahav */ template struct ToChar { static const char char_ = (IsLetter::result_ ? (Key - Qt::Key_A) + 'A' : (IsDigit::result_ ? (Key - Qt::Key_0) + '0' : 0)); static char transform(char c) { if (c >= Qt::Key_0 && c <= Qt::Key_9) return (c - Qt::Key_0) + '0'; if (c >= Qt::Key_A && c <= Qt::Key_Z) return (c - Qt::Key_A) + 'A'; return 0; } }; /** * Provides compile- and run-time functions for translating a key into an ASCII * control character. * @author Elad Lahav */ template struct ToControlChar { static const char char_ = (IsLetter::result_ ? (Key - Qt::Key_A) + 1 : 0); static const uchar uchar_ = static_cast(char_); static char transform(char c) { if (c >= Qt::Key_A && c <= Qt::Key_Z) return (c - Qt::Key_A) + 1; return 0; } }; } // namespace QtKey namespace Editor { /** * Implements the empty (move) action for a move command. * @author Elad Lahav */ struct MoveAction { static ViCommand::ProcessResult action(ViScintilla* editor) { (void)editor; return ViCommand::Done; } }; /** * Implements the yank action for a move command. * @author Elad Lahav */ struct YankAction { static ViCommand::ProcessResult action(ViScintilla* editor) { // Copy selected text. editor->copy(); // Clear selection. int position = editor->SendScintilla(QsciScintillaBase::SCI_GETSELECTIONSTART); editor->SendScintilla(QsciScintillaBase::SCI_GOTOPOS, position); return ViCommand::Done; } }; /** * Implements the cut action for a move command. * @author Elad Lahav */ struct CutAction { static ViCommand::ProcessResult action(ViScintilla* editor) { // Cut selected text. editor->cut(); return ViCommand::Done; } }; /** * Implements the change (delete+exit normal mode) action for a move command. * @author Elad Lahav */ struct ChangeAction { static ViCommand::ProcessResult action(ViScintilla* editor) { // Delete selected text and exit normal mode. editor->removeSelectedText(); return ViCommand::Exit; } }; /** * Handles cursor movement commands. * @author Elad Lahav */ template struct MoveCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { bool relative; uint message; switch (key) { case 'l': // Go right characters. relative = true; message = Select ? QsciScintillaBase::SCI_CHARRIGHTEXTEND : QsciScintillaBase::SCI_CHARRIGHT; break; case 'h': // Go left characters. relative = true; message = Select ? QsciScintillaBase::SCI_CHARLEFTEXTEND : QsciScintillaBase::SCI_CHARLEFT; break; case 'k': // Go up lines. relative = true; message = Select ? QsciScintillaBase::SCI_LINEUPEXTEND : QsciScintillaBase::SCI_LINEUP; break; case 'j': // Go down lines. relative = true; message = Select ? QsciScintillaBase::SCI_LINEDOWNEXTEND : QsciScintillaBase::SCI_LINEDOWN; break; case 'w': // Go left words relative = true; message = Select ? QsciScintillaBase::SCI_WORDRIGHTEXTEND : QsciScintillaBase::SCI_WORDRIGHT; break; case '0': // Go to the beginning of the line. relative = false; message = Select ? QsciScintillaBase::SCI_HOMEEXTEND : QsciScintillaBase::SCI_HOME; break; case '$': // Go to the end of the line. relative = false; message = Select ? QsciScintillaBase::SCI_LINEENDEXTEND : QsciScintillaBase::SCI_LINEEND; break; case 'g': // Go to the beginning of the file. relative = false; message = Select ? QsciScintillaBase::SCI_DOCUMENTSTARTEXTEND : QsciScintillaBase::SCI_DOCUMENTSTART; break; case 'G': // Go to the end of the file. relative = false; message = Select ? QsciScintillaBase::SCI_DOCUMENTENDEXTEND : QsciScintillaBase::SCI_DOCUMENTEND; break; default: return NotHandled; } // Compute the multiplier value. int multiplier = 1; if (relative && seq.length() > 1) { bool ok; multiplier = CharSequence(seq, 0, -1).toUInt(&ok); if (!ok) return NotHandled; } // Move the cursor. for (int i = 0; i < multiplier; i++) editor->SendScintilla(message); return ActionT::action(editor); } }; /** * Common handler for commands that take the form . Examples * include yank, cut and change. * Supported variants include: * - : do action on a the current line, * - : do action on lines, * - : do action on a range starting from the current cursor * position to the one resulting from the move command. * @author Elad Lahav */ template struct XyXCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { switch (key) { case C: // Check if this is the first occurrence of C. if (seq.length() == 1) return Continue; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return Continue; case '0': if (seq.length() > 2) return Continue; // Fall through... default: { MoveCommand moveCmd; return moveCmd.processKey(key, editor, CharSequence(seq, 1, 0)); } } // Got here on a second occurrence of C. // Perform the action on a number of whole lines. int multiplier = 1; if (seq.length() > 2) { bool ok; multiplier = CharSequence(seq, 1, -1).toUInt(&ok); if (!ok) return NotHandled; } // Select the given number of lines. editor->SendScintilla(QsciScintillaBase::SCI_VCHOME); for (int i = 0; i < multiplier; i++) editor->SendScintilla(QsciScintillaBase::SCI_LINEDOWNEXTEND); // Perform the action on the selected lines. return ActionT::action(editor); } }; /** * Pastes text from the clipboard. * @author Elad Lahav */ struct PasteCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { (void)seq; switch (key) { case 'P': // Paste here. editor->paste(); return Done; case 'p': break; default: return NotHandled; } // Get the current cursor position. int line, column; editor->getCursorPosition(&line, &column); // TODO: Is this the right behaviour? if (column == 0) line++; else column++; // Move to the new position and paste. editor->setCursorPosition(line, column); editor->paste(); return Done; } }; /** * Aborts Vi mode. * Different keys place the cursor in different locations: * - i: Current position * - a: Next column * - I: Beginning of current line * - A: End of current line * @author Elad Lahav */ struct InsertCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { (void)seq; // Get the current cursor position. int line, column; editor->getCursorPosition(&line, &column); switch (key) { case 'i': break; case 'a': column++; break; case 'I': column = 0; break; case 'A': column = editor->lineLength(line) - 1; break; default: return NotHandled; } // Move to the new position and exit normal mode. editor->setCursorPosition(line, column); return Exit; } }; /** * Performs the undo (u) and redo (Ctrl+r) actions. * @author Elad Lahav */ struct UndoRedoCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { int multiplier = 1; if (seq.length() > 1) { bool ok; multiplier = CharSequence(seq, 0, -1).toUInt(&ok); if (!ok) return NotHandled; } // Get the current cursor position. switch (key) { case 'u': for (int i = 0; i < multiplier; i++) editor->undo(); break; case QtKey::ToControlChar::char_: for (int i = 0; i < multiplier; i++) editor->redo(); break; default: return NotHandled; } return Done; } }; /** * Creates a new line, either above or below the current one, and exits normal * mode. */ struct OpenLineCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { (void)seq; // Get the current cursor position. int line, column; editor->getCursorPosition(&line, &column); switch (key) { case 'o': line++; break; case 'O': break; default: return NotHandled; } // Add a line at the new position and exit normal mode. editor->setCursorPosition(line, 0); editor->insert("\n"); return Exit; } }; /** * Handles all commands that start with a number (other than 0). * Currently supports movement, undo and redo only. Yank, delete, change, etc. * must start with a character (e.g., d2d rather than 2dd). * @author Elad Lahav */ struct NumPrefixCommand : public ViCommand { ProcessResult processKey(char key, ViScintilla* editor, const CharSequence& seq) { // Consume digits. if (key >= '0' && key <= '9') return Continue; switch (key) { case 'l': case 'h': case 'k': case 'j': case 'w': return MoveCommand<>().processKey(key, editor, seq); case 'u': case QtKey::ToControlChar::char_: return UndoRedoCommand().processKey(key, editor, seq); } return NotHandled; } }; ViScintilla::CommandMap ViScintilla::commandMap_; /** * Class constructor. * @param parent Parent widget */ ViScintilla::ViScintilla(QWidget* parent) : QsciScintilla(parent), mode_(Disabled), curCommand_(NULL) { } /** * Class destructor. */ ViScintilla::~ViScintilla() { } /** * Changes the edit mode. * @param mode The new mode to set */ void ViScintilla::setEditMode(EditMode mode) { if (mode != mode_) { // Set the new mode. mode_ = mode; // Change the caret style. // TODO: Handle overwrite in disabled/insert mode. switch (mode_) { case Disabled: case InsertMode: SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_LINE); break; case NormalMode: case VisualMode: SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_BLOCK); break; } // Notify of the change. emit editModeChanged(mode_); } } /** * Handles a key press. * If Vi compatibility is disabled or the current editing mode is insert, the * event is handled by Scintilla. Otherwise, the key is intercepted and * interpreted by the Vi command structure. * @param event The key event */ void ViScintilla::keyPressEvent(QKeyEvent* event) { switch (mode_) { case Disabled: // Let Scintilla handle all events. QsciScintilla::keyPressEvent(event); return; case InsertMode: // Intercept the ESC key for entering normal mode. if ((event->key() == Qt::Key_Escape) && (event->modifiers() == Qt::NoModifier)) { setEditMode(NormalMode); event->setAccepted(true); } else { // Anything but ESC. QsciScintilla::keyPressEvent(event); } return; case NormalMode: case VisualMode: break; } event->setAccepted(false); // Translate keys, so that we only deal with ASCII characters. char key, dispKey = 0; switch (event->modifiers()) { case Qt::ControlModifier: key = QtKey::ToControlChar<>::transform(event->key()); dispKey = QtKey::ToChar<>::transform(event->key()); break; case Qt::NoModifier: switch (event->key()) { case Qt::Key_Right: key = 'l'; break; case Qt::Key_Left: key = 'h'; break; case Qt::Key_Up: key = 'k'; break; case Qt::Key_Down: key = 'j'; break; case Qt::Key_Escape: // Abort the current command. if (curCommand_) { emit message(QString("Aborted: ") + cmdString_, 1000); curCommand_ = NULL; cmdSequence_.clear(); cmdString_ = ""; } event->setAccepted(true); return; default: key = event->text()[0].toAscii(); } break; case Qt::ShiftModifier: key = event->text()[0].toAscii(); break; default: return; } if (key == 0) return; // Add to the current command sequence. cmdSequence_.append(key); if (event->modifiers() & Qt::ControlModifier) cmdString_.append("(Ctrl)"); cmdString_.append(dispKey ? dispKey : key); // Process the key event. ViCommand::ProcessResult result; if (curCommand_) { // If a command is in progress, let it process the key. result = curCommand_->processKey(key, this, cmdSequence_); } else { // This is the first key in a new command. // Check which command is associated with this key. curCommand_ = commandMap_.command(key); if (curCommand_) result = curCommand_->processKey(key, this, cmdSequence_); else result = ViCommand::NotHandled; } switch (result) { case ViCommand::Continue: // A command is in progress. emit message(cmdString_, 1000); break; case ViCommand::Exit: // Return to insert mode. setEditMode(InsertMode); // Fall through... case ViCommand::Done: curCommand_ = NULL; // Report multi-character commands. if (cmdSequence_.length() > 1) emit message(cmdString_, 1000); cmdSequence_.clear(); cmdString_ = ""; break; case ViCommand::NotHandled: // Unrecognised command sequence. curCommand_ = NULL; emit message(tr("Bad sequence: %1").arg(cmdString_), 2000); cmdSequence_.clear(); cmdString_ = ""; return; } event->setAccepted(true); } /** * Class constructor. * Creates the command objects, and puts them in the key-to-command map. */ ViScintilla::CommandMap::CommandMap() { ViCommand* moveCmd = new MoveCommand<>; ViCommand* yankCmd = new XyXCommand<'y', YankAction>; ViCommand* cutCmd = new XyXCommand<'d', CutAction>; ViCommand* changeCmd = new XyXCommand<'c', ChangeAction>; ViCommand* pasteCmd = new PasteCommand; ViCommand* insCmd = new InsertCommand; ViCommand* undoCmd = new UndoRedoCommand; ViCommand* numCmd = new NumPrefixCommand; ViCommand* openCmd = new OpenLineCommand; // Add all commands to a list, so they can be deleted when the map is // destroyed. cmdList_ << moveCmd << yankCmd << cutCmd << changeCmd << pasteCmd << insCmd << undoCmd << numCmd; // Clear the map. memset(cmdMap_, 0, sizeof(cmdMap_)); // Insert commands to the map. cmdMap_['0'] = moveCmd; cmdMap_['1'] = numCmd; cmdMap_['2'] = numCmd; cmdMap_['3'] = numCmd; cmdMap_['4'] = numCmd; cmdMap_['5'] = numCmd; cmdMap_['6'] = numCmd; cmdMap_['7'] = numCmd; cmdMap_['8'] = numCmd; cmdMap_['9'] = numCmd; cmdMap_['l'] = moveCmd; cmdMap_['h'] = moveCmd; cmdMap_['k'] = moveCmd; cmdMap_['j'] = moveCmd; cmdMap_['w'] = moveCmd; cmdMap_['$'] = moveCmd; cmdMap_['g'] = moveCmd; cmdMap_['G'] = moveCmd; cmdMap_['y'] = yankCmd; cmdMap_['d'] = cutCmd; cmdMap_['c'] = changeCmd; cmdMap_['p'] = pasteCmd; cmdMap_['P'] = pasteCmd; cmdMap_['i'] = insCmd; cmdMap_['a'] = insCmd; cmdMap_['I'] = insCmd; cmdMap_['A'] = insCmd; cmdMap_['u'] = undoCmd; cmdMap_[QtKey::ToControlChar::uchar_] = undoCmd; cmdMap_['o'] = openCmd; cmdMap_['O'] = openCmd; } /** * Class destructor. * Deletes the command objects. */ ViScintilla::CommandMap::~CommandMap() { foreach (ViCommand* cmd, cmdList_) delete cmd; } /** * Returns the command handling the given character. * @param c The character to map * @return The handling command, NULL if no command is assigned to this * character. */ ViCommand* ViScintilla::CommandMap::command(char c) { int index = static_cast(c); if (index < 0 || index >= 0x100) return NULL; return cmdMap_[index]; } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/config.h0000644000175000001440000000712611156714354015111 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_CONFIG_H__ #define __EDITOR_CONFIG_H__ #include #include #include #include #include #include "viscintilla.h" namespace KScope { namespace Editor { class Editor; class LexerStyleModel; class CommonLexer; /** * Manages editor configuration. * @author Elad Lahav */ class Config : public QObject { Q_OBJECT public: Config(QObject* parent = NULL); ~Config(); void load(QSettings&); void store(QSettings&) const; void apply(Editor*) const; QsciLexer* lexer(const QString&) const; typedef QList LexerList; private: /** * Whether to highlight the current line. */ bool hlCurLine_; /** * Whether whitespace markers should be shown. */ bool visibleWSpace_; /** * Whether to show line numbers in the margin. */ bool marginLineNumbers_; /** * The column in which to place the end-of-line marker (0 to disable). */ int eolMarkerColumn_; /** * Whether to use tabs for indentation. */ bool indentTabs_; /** * The tab width, in characters. */ int tabWidth_; /** * The Vi mode in which editors should be started. */ ViScintilla::EditMode viDefaultMode_; /** * The common defaults lexers. */ CommonLexer* commonLexer_; /** * C/C++ lexer. */ QsciLexerCPP* cppLexer_; /** * Makefile lexer. */ QsciLexerMakefile* makeLexer_; /** * Shell script lexer. */ QsciLexerBash* bashLexer_; /** * A list of the above lexers for batch operations. */ LexerList lexers_; /** * Used to configure lexer styles. */ LexerStyleModel* styleModel_; /** * Maps file name patterns to lexers. */ struct { struct Pair { QRegExp re_; QsciLexer* lexer_; Pair(const QString& pattern) : re_(pattern, Qt::CaseSensitive, QRegExp::Wildcard), lexer_(NULL) {} void operator=(QsciLexer* lexer) { lexer_ = lexer; } }; QList map_; Pair& operator[](const QString& pattern) { map_.append(Pair(pattern)); return map_.last(); } QsciLexer* find(const QString& text) const { QList::ConstIterator itr; for (itr = map_.begin(); itr != map_.end(); ++itr) { if ((*itr).re_.exactMatch(text)) return (*itr).lexer_; } return NULL; } void clear() { map_.clear(); } } lexerMap_; friend class ConfigDialog; void fromEditor(Editor* editor = NULL); template static inline void loadValue(const QSettings& settings, T& val, const QString& key, const T& defVal) { QVariant var = settings.value(key, defVal); val = var.value(); } }; } // namespace Editor } // namespace KScope #endif // __EDITOR_CONFIG_H__ kscope-1.9.4/editor/editor.h0000644000175000001440000000666211156714354015136 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_EDITOR_H__ #define __EDITOR_EDITOR_H__ #include #include #include "viscintilla.h" namespace KScope { namespace Editor { /** * An QScintilla editor widget used to view/edit files. * @author Elad Lahav */ class Editor : public ViScintilla { Q_OBJECT public: Editor(QWidget* parent = 0); ~Editor(); /** * Options for text searches. */ struct SearchOptions { /** * Whether the pattern represents a regular expression. */ bool regExp_; /** * Whether the search is case sensitive. */ bool caseSensitive_; /** * Whether to look for whole words only. */ bool wholeWordsOnly_; /** * Whether the search should wrap at the end of the document. */ bool wrap_; /** * Whether to search backward in the document. */ bool backward_; }; bool load(const QString&, QsciLexer* lexer); bool save(); bool canClose(); void moveCursor(uint, uint); QString currentSymbol() const; void setFocus(); void getCurrentLocation(Core::Location&); QString title() const; /** * @return The path of the file loaded in the editor, an empty string for * a new file */ QString path() const { return path_; } /** * @param index The unique index used to generate the title of the editor */ void setNewFileIndex(uint index) { newFileIndex_ = index; } public slots: void search(); void searchNext(); void gotoLine(); void gotoBlockBegin(); signals: /** * Notifies the container that the editor with the given title is being * closed. * @param title The unique title of the editor being closed */ void closed(const QString& title); /** * Notifies the container of a change to the editor's title. * @param oldTitle * @param newTitle */ void titleChanged(const QString& oldTitle, const QString& newTitle); protected: void closeEvent(QCloseEvent*); private: /** * The file being edited. */ QString path_; /** * For new files only, stores the index used to create a unique title for * this editor. */ uint newFileIndex_; /** * Whether a file is currently being loaded. */ bool isLoading_; /** * The line to go to when loading finishes. */ uint onLoadLine_; /** * The column to go to when loading finishes. */ uint onLoadColumn_; /** * Whether to set the keyboard focus when loading finishes. */ bool onLoadFocus_; private slots: void loadDone(const QString&); }; } // namespace Editor } // namespace KScope #endif // __EDITOR_EDITOR_H__ kscope-1.9.4/editor/configdialog.ui0000644000175000001440000003576111156714354016465 0ustar elahavusers ConfigDialog 0 0 602 476 Configure Editor 0 Display Highlight current line Show white space markers Show line numbers in margin Show end-of-line marker Qt::Horizontal 40 20 Column: false Qt::Vertical 20 41 Indentation Indent with tabs Tab Width Qt::Horizontal 173 20 Language Options Language Qt::Horizontal 40 20 Maintain indentation Indent by opening braces Indent by closing braces Qt::Vertical 20 132 Styles Styles false Properties true Qt::Horizontal 40 20 Make child styles inherit this property &Apply to Sub-Styles Load styles from an external file &Import... Store styles in an external file &Export... Qt::Horizontal 168 28 Revert to default styles &Reset Styles Miscellaneous Default Vi Mode Qt::Horizontal 40 20 Qt::Vertical 20 337 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox tabs_ buttonBox accepted() ConfigDialog accept() 251 466 359 262 buttonBox rejected() ConfigDialog reject() 185 466 355 289 indentTabsCheck_ toggled(bool) widget setEnabled(bool) 49 59 166 101 indentLanguageCombo_ currentIndexChanged(int) ConfigDialog indentLanguageChanged(int) 119 156 429 149 resetButton_ clicked() ConfigDialog resetStyles() 580 389 443 314 applyInheritButton_ clicked() ConfigDialog applyInheritance() 538 368 598 353 importButton_ clicked() ConfigDialog importStyles() 74 402 4 431 exportButton_ clicked() ConfigDialog exportStyles() 159 402 101 471 eolMarkerCheck_ toggled(bool) eolMarkerSpin_ setEnabled(bool) 108 133 542 130 indentLanguageChanged(int) resetStyles() applyInheritance() importStyles() exportStyles() kscope-1.9.4/editor/config.cpp0000644000175000001440000001671111156714354015444 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include #include "config.h" #include "editor.h" #include "lexerstylemodel.h" namespace KScope { namespace Editor { /** * A special lexer used to create a common default style for all other lexers. * This class serves two purposes: * 1. Allows style properties to be inherited by all lexers (e.g., for setting * a single, common font); * 2. Provides a default lexer for files that are not handled by any of the * pre-defined lexers. * @author Elad Lahav */ class CommonLexer : public QsciLexer { public: /** * Class constructor. * @param parent Parent object */ CommonLexer(QObject* parent) : QsciLexer(parent) {} /** * Class destructor. */ ~CommonLexer() {} /** * @return A string identifying the language handled by the lexer */ const char* language() const { return tr("Common").toLatin1(); } /** * @return A string identifying the lexer */ const char* lexer() const { return "common"; } /** * Provides a name for the given style ID. * @param style The style ID * @return The name of the style, or an empty string if the style does not * exist */ QString description(int style) const { if (style == 0) return tr("Default"); return QString(); } /** * @return The ID of the default style for this lexer */ int defaultStyle() const { return 0; } }; /** * The sole purpose of this class is to provide a fix a couple of bugs in * QsciLexerCPP: * 1. The description of the UUID style is not handled, causing the style * detection mechanism to stop before all styles are found.; * 2. The default text colour is set to grey, rather than black * @author Elad Lahav */ class CPPLexer : public QsciLexerCPP { public: /** * Class constructor. * @param parent Parent object */ CPPLexer(QObject* parent) : QsciLexerCPP(parent) {} /** * Class destructor. */ ~CPPLexer() {} /** * Provides a description string for each style. * Fixes the bug in QsciLexerCPP::description(). * @param style The style ID * @return The style description or an empty string if the style does not * exist */ QString description(int style) const { if (style == UUID) return "UUID"; return QsciLexerCPP::description(style); } /** * Returns the default text colour for the given style. * @param style The requested style * @return The style's default colour */ QColor defaultColor(int style) const { if (style == Default) return QColor(0, 0, 0); return QsciLexerCPP::defaultColor(style); } }; /** * Class constructor. * @param parent Parent object */ Config::Config(QObject* parent) : QObject(parent) { // Create the lexers. commonLexer_ = new CommonLexer(this); cppLexer_ = new CPPLexer(this); makeLexer_ = new QsciLexerMakefile(this); bashLexer_ = new QsciLexerBash(this); lexers_ << commonLexer_ << cppLexer_ << makeLexer_ << bashLexer_; // Create the lexer style model. styleModel_ = new LexerStyleModel(lexers_, this); } /** * Class destructor. */ Config::~Config() { } /** * Reads editor configuration parameters from a QSettings object. * @param settings The object to read from */ void Config::load(QSettings& settings) { // Get the current (default) configuration. Editor editor; // Read values from the settings object. loadValue(settings, hlCurLine_, "HighlightCurrentLine", false); loadValue(settings, visibleWSpace_, "VisibleWhitespace", false); loadValue(settings, marginLineNumbers_, "LineNumbersInMargin", false); loadValue(settings, eolMarkerColumn_, "EOLMarkerColumn", 0); loadValue(settings, indentTabs_, "IndentWithTabs", editor.indentationsUseTabs()); loadValue(settings, tabWidth_, "TabWidth", editor.tabWidth()); uint viMode; loadValue(settings, viMode, "ViMode", (uint)ViScintilla::Disabled); viDefaultMode_ = static_cast(viMode); // Load the C lexer parameters. // Ignore the exception thrown by load(), which is the result of not // finding the style magic key in the settings file. This happens if styles // were never modified by the user, and is thus benign. styleModel_->load(settings, true); styleModel_->updateLexers(); // Create the file to lexer map. // TODO: Make this configurable. lexerMap_.clear(); lexerMap_["*.c"] = cppLexer_; lexerMap_["*.cc"] = cppLexer_; lexerMap_["*.cpp"] = cppLexer_; lexerMap_["*.h"] = cppLexer_; lexerMap_["*.hpp"] = cppLexer_; lexerMap_["Makefile*"] = makeLexer_; lexerMap_["*.sh"] = bashLexer_; } /** * Writes the current configuration parameters to a QSettings object. * @param settings The object to write to */ void Config::store(QSettings& settings) const { // Store editor configuration. settings.setValue("HighlightCurrentLine", hlCurLine_); settings.setValue("VisibleWhitespace", visibleWSpace_); settings.setValue("LineNumbersInMargin", marginLineNumbers_); settings.setValue("EOLMarkerColumn", eolMarkerColumn_); settings.setValue("IndentWithTabs", indentTabs_); settings.setValue("TabWidth", tabWidth_); settings.setValue("ViMode", viDefaultMode_); styleModel_->store(settings, true); } /** * Updates the settings of the current editor to reflect the current * configuration parameters. * @param editor The editor to which to apply the configuration */ void Config::apply(Editor* editor) const { editor->setCaretLineVisible(hlCurLine_); editor->setWhitespaceVisibility (visibleWSpace_ ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible); if (marginLineNumbers_) { editor->setMarginLineNumbers(2, true); QFont font = commonLexer_->font(0); int width = QFontMetrics(font).width("8888"); editor->setMarginsFont(font); editor->setMarginWidth(2, width); } else { editor->setMarginLineNumbers(2, false); editor->setMarginWidth(2, 0); } if (eolMarkerColumn_ > 0) { editor->setEdgeMode(QsciScintilla::EdgeLine); editor->setEdgeColumn(eolMarkerColumn_); } else { editor->setEdgeMode(QsciScintilla::EdgeNone); } editor->setIndentationsUseTabs(indentTabs_); editor->setTabWidth(tabWidth_); editor->setFont(commonLexer_->font(0)); editor->setColor(commonLexer_->color(0)); editor->setPaper(commonLexer_->paper(0)); editor->setEditMode(viDefaultMode_); if (editor->lexer()) editor->lexer()->refreshProperties(); } /** * Provides a lexer for the given file. * @param path The path to the file * @return The appropriate lexer */ QsciLexer* Config::lexer(const QString& path) const { QString name = QFileInfo(path).fileName(); QsciLexer* lexer = lexerMap_.find(path); return lexer == NULL ? commonLexer_ : lexer; } } // namespace Editor } // namespace KScope kscope-1.9.4/editor/findtextdialog.h0000644000175000001440000000336411156714354016651 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_FINDTEXTDIALOG_H__ #define __EDITOR_FINDTEXTDIALOG_H__ #include #include #include "ui_findtextdialog.h" #include "editor.h" namespace KScope { namespace Editor { /** * A simple dialogue for searching text within an editor window. * @author Elad Lahav */ class FindTextDialog : public QDialog, public Ui::FindTextDialog { Q_OBJECT public: FindTextDialog(QWidget* parent = 0); ~FindTextDialog(); static int promptPattern(QString&, Editor::SearchOptions&, QWidget* parent = NULL); private: /** * A list of previously-searched patterns. */ static QStringList historyList_; /** * */ static Editor::SearchOptions options_; }; } // namespace Editor } // namespace KScope #endif // __EDITOR_FINDTEXTDIALOG_H__ kscope-1.9.4/editor/configdialog.h0000644000175000001440000000400211156714354016257 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef __EDITOR_CONFIGDIALOG_H__ #define __EDITOR_CONFIGDIALOG_H__ #include #include #include "ui_configdialog.h" #include "config.h" namespace KScope { namespace Editor { class LexerStyleModel; /** * A dialogue for configuring a QScintilla editor. * Unfortunately, QScintilla does not provide such a dialogue * @author Elad Lahav */ class ConfigDialog : public QDialog, public Ui::ConfigDialog { Q_OBJECT public: ConfigDialog(const Config&, QWidget* parent = NULL); ~ConfigDialog(); void getConfig(Config&); signals: /** * Used to notify the lexer model of a change to the default font. */ void defaultFontChanged(); private: QStandardItemModel* lexerModel_; LexerStyleModel* styleModel_; private slots: void indentLanguageChanged(int); void resetStyles(); void importStyles(); void exportStyles(); void editStyle(const QModelIndex&); void editProperty(const QModelIndex&, const QVariant&); void applyInheritance(); }; } // namespace Editor } // namespace KScope #endif // __EDITOR_CONFIGDIALOG_H__ kscope-1.9.4/editor/findtextdialog.ui0000644000175000001440000000625311156714354017037 0ustar elahavusers FindTextDialog 0 0 352 234 Find Pattern 0 0 true Regular Expression Case Sensitive Whole Words Only Wrap Search Search Backwards Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() FindTextDialog accept() 341 223 157 274 buttonBox rejected() FindTextDialog reject() 341 223 286 274 kscope-1.9.4/editor/findtextdialog.cpp0000644000175000001440000000637111156714354017205 0ustar elahavusers/*************************************************************************** * Copyright (C) 2007-2009 by Elad Lahav * elad_lahav@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #include "findtextdialog.h" namespace KScope { namespace Editor { QStringList FindTextDialog::historyList_; Editor::SearchOptions FindTextDialog::options_; /** * Class constructor. * @param parent Parent widget */ FindTextDialog::FindTextDialog(QWidget* parent) : QDialog(parent), Ui::FindTextDialog() { setupUi(this); } /** * Class destructor. */ FindTextDialog::~FindTextDialog() { } /** * Displays the search dialogue. * This is a convenience static function, which remembers the last settings, as * well as keeps a history of searched patterns. * @param pattern Default pattern (input) and selected pattern (output) * @param options Holds the selected search options * @param parent Parent widget * @return The result of calling exec() for a dialogue object */ int FindTextDialog::promptPattern(QString& pattern, Editor::SearchOptions& options, QWidget* parent) { FindTextDialog dlg(parent); // Adjust dialogue controls. dlg.patternCombo_->addItems(historyList_); dlg.patternCombo_->lineEdit()->setText(pattern); dlg.patternCombo_->lineEdit()->selectAll(); dlg.regExpCheck_->setChecked(options_.regExp_); dlg.caseSensitiveCheck_->setChecked(options_.caseSensitive_); dlg.wholeWordsCheck_->setChecked(options_.wholeWordsOnly_); dlg.wrapCheck_->setChecked(options_.wrap_); dlg.backwardsCheck_->setChecked(options_.backward_); // Show the dialogue. if (dlg.exec() != QDialog::Accepted) return QDialog::Rejected; // Get the current search parameters. // This will both save the current options as well as create a copy for the // caller. pattern = dlg.patternCombo_->lineEdit()->text(); options_.regExp_ = dlg.regExpCheck_->isChecked(); options_.caseSensitive_ = dlg.caseSensitiveCheck_->isChecked();; options_.wholeWordsOnly_ = dlg.wholeWordsCheck_->isChecked(); options_.wrap_ = dlg.wrapCheck_->isChecked(); options_.backward_ = dlg.backwardsCheck_->isChecked(); options = options_; // Add to the history list, if pattern is not already there. if (!historyList_.contains(pattern)) { // Restrict the size of the list to 20 entries. if (historyList_.size() == 20) historyList_.removeLast(); historyList_.prepend(pattern); } return QDialog::Accepted; } } // namespace Editor } // namespace KScope kscope-1.9.4/Doxyfile0000644000175000001440000002424511156714355013715 0ustar elahavusers# Doxyfile 1.5.1-KDevelop #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = KScope PROJECT_NUMBER = 1.9.0 OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = /home/elahav/ STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = YES HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = /home/elahav/projects/KScope FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY \ *.C \ *.H \ *.tlh \ *.diff \ *.patch \ *.moc \ *.xpm \ *.dox RECURSIVE = yes EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = yes XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = KScope.tag ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO kscope-1.9.4/ChangeLog0000644000175000001440000000433111156714355013753 0ustar elahavusers1.9.4 (2009-03-12) * Bug fix: New projects were not created properly 1.9.3 (2009-03-12) * New: Limited Vi compatibility (several movement and editing commands implemented) * New: Hierarchical editor styles * New: Import/export editor styles * New: More visual options for the editor * New: Go to beginning of block menu action * New: Handle changes to project configuration parameters * Improved: Better handling of editor menu actions * Bug fix: Show typedefs in local tags * Bug fix: Clear the query type list before prompting for a new query * Compilation fix: Avoid error in createIndex() on a 64-bit OS 1.9.2 (2009-02-13) * New: "Open Project" dialogue with recent projects * New: Added a "Close All" action to the file menu * New: Pattern history in the query dialogue * New: A context menu for filtering query results and for reexecuting queries * New: Menu command for switching the UI between tabbed and sub-window views * New: Show cursor position for the active editor * Improved: Restore maximised editor windows when loading a session * Improved: Handle name changes to files * Improved: Close all open queries when closing a project * Improved: The build progress bar no longer changes the height of the status bar * Improved: Many enhancements to the editor configuration dialogue * Bug fix: Do not requery expanded empty items upon loading from XML * Bug fix: Do not crash when a new file is closed * Bug fix: Resize columns and set root path in restored queries * Bug fix: Clear location history when closing a project * Bug fix: Cscope parser should remove whitespace after the line number * Bug fix: Adjust column width in the location history view * Bug fix: More fixes to the handling of the active editor 1.9.1 (2009-01-26) * New: Save/restore queries as part of a session * Improved: Better session handling * Bug fix: Several fixes to the Cscope output parser * Bug fix: Fixed crash when selecting the first item in the history * Bug fix: Use the correct path when loading project files * Bug fix: Correct detection of the active editor * Compilation fix: Explicitly link libkscope_cscope with libkscope_core * Documentation: Added instructions for running KScope to the INSTALL file 1.9.0 (2009-01-10) * Initial release of the new code kscope-1.9.4/config0000644000175000001440000000137211156714355013373 0ustar elahavusers# Common configuration options for all project files. # -------------------------- BEGIN: EDIT ME ----------------------------------- # Change this value to the installation root path. # Executables will be installed under INSTALL_PATH/bin, libraries under # INSTALL_PATH/lib, etc. INSTALL_PATH = /usr/local # The root path of the QScintilla installation. # KScope expects to find QScintilla's include files under # QSCI_ROOT_PATH/include/Qsci and the library under QSCI_ROOT_PATH/lib. QSCI_ROOT_PATH = /usr # --------------------------- END: EDIT ME ------------------------------------ # The following lines should normally not be edited. CONFIG += debug_and_release \ warn_all CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT QT += xml