/*************************************************************************** * Copyright (C) 2005 by Jens Herden * * jens@kdewebdev.org * * * * 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., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "projectviewprojectconfig.h" #include "projectviewconfig.h" #include "projectviewpart.h" #include "filelist_widget.h" #include "toolbarguibuilder.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef KDevGenericFactory projectviewFactory; KDevPluginInfo data("kdevfilelist"); K_EXPORT_COMPONENT_FACTORY(libkdevfilelist, projectviewFactory(data)) #define GLOBALDOC_OPTIONS 1 #define PROJECTDOC_OPTIONS 2 ProjectviewPart::ProjectviewPart(TQObject *tqparent, const char *name, const TQStringList &/*args*/) : KDevPlugin(&data, tqparent, name ? name : "FileListPart") { setInstance(projectviewFactory::instance()); setXMLFile("kdevfilelist.rc"); setupActions(); m_configProxy = new ConfigWidgetProxy(core()); m_configProxy->createGlobalConfigPage(i18n("File List"), GLOBALDOC_OPTIONS, info()->icon()); m_configProxy->createProjectConfigPage(i18n("File List"), PROJECTDOC_OPTIONS, info()->icon()); connect(m_configProxy, TQT_SIGNAL(insertConfigWidget(const KDialogBase*, TQWidget*, unsigned int)), this, TQT_SLOT(insertConfigWidget(const KDialogBase*, TQWidget*, unsigned int))); connect(core(), TQT_SIGNAL(contextMenu(TQPopupMenu *, const Context *)), this, TQT_SLOT(contextMenu(TQPopupMenu *, const Context *))); connect(core(), TQT_SIGNAL(projectOpened()), this, TQT_SLOT(projectOpened())); connect(core(), TQT_SIGNAL(projectClosed()), this, TQT_SLOT(projectClosed())); KConfig * config = kapp->config(); config->setGroup("File List Plugin"); if (config->readBoolEntry("ToolbarInToolview", true)) { m_toolbarWidget = new TQVBox(0, "toolbarContainer"); m_toolbarWidget->setHidden(true); m_guibuilder = new ToolbarGUIBuilder(m_toolbarWidget, mainWindow()->main()); setClientBuilder(m_guibuilder); } m_restored = false; TQTimer::singleShot(0, this, TQT_SLOT(init())); } ProjectviewPart::~ProjectviewPart() { delete m_configProxy; delete m_guibuilder; if ( m_widget ) { mainWindow()->removeView( m_widget ); delete m_widget; // deletes the tqchildren as well } } void ProjectviewPart::restorePartialProjectSession(const TQDomElement * el) { m_projectViews.clear(); // remove the global views m_restored = true; if (!el) { return; } // get the base of the project TQString urlStr = project()->projectDirectory(); if (KURL::isRelativeURL(urlStr)) { m_projectBase.setProtocol("file"); m_projectBase.setPath(urlStr); } else { m_projectBase = KURL::fromPathOrURL(urlStr); } m_projectBase.adjustPath(+1); // just in case // read all the views TQDomNodeList domList = el->elementsByTagName("projectview"); uint len = domList.length(); for (uint i = 0; i < len; ++i) { const TQDomElement viewEl = domList.item(i).toElement(); if (viewEl.isNull()) { continue; } FileInfoList urlList; TQDomNodeList fileList = viewEl.elementsByTagName("file"); uint len2 = fileList.length(); for (uint i2 = 0; i2 < len2; ++i2) { const TQDomElement fileEl = fileList.item(i2).toElement(); if (!fileEl.isNull()) { bool ok; int line = -1; TQString attr = fileEl.attribute("line"); if (! attr.isNull()) { line = attr.toInt(&ok); if (!ok) line = -1; } int col = -1; attr = fileEl.attribute("col"); if (! attr.isNull()) { col = attr.toInt(&ok); if (!ok) col = -1; } TQString encoding = ""; attr = fileEl.attribute("encoding"); if (! attr.isNull()) { encoding = attr; } TQString urlStr = fileEl.attribute("url"); if (KURL::isRelativeURL(urlStr)) { KURL url = m_projectBase; url.addPath(urlStr); urlList.append(FileInfo(url, line, col, encoding)); } else urlList.append(FileInfo(KURL::fromPathOrURL(urlStr), line, col, encoding)); } } m_projectViews.insert(viewEl.attribute("name"), urlList); } // read default view domList = el->elementsByTagName("defaultview"); if (domList.length() > 0) { m_defaultProjectView = domList.item(0).toElement().attribute("name"); if (!m_defaultProjectView.isEmpty()) { slotOpenProjectView(m_defaultProjectView); } } else { m_defaultProjectView = ""; } } void ProjectviewPart::savePartialProjectSession(TQDomElement * el) { if (!el || m_projectViews.empty()) { return; } TQDomDocument domDoc = el->ownerDocument(); if (domDoc.isNull()) { return; } // write all views ViewMap::ConstIterator it; for (it = m_projectViews.constBegin(); it != m_projectViews.constEnd(); ++it) { // we create the view even if there is no file inside, might be wanted by the user TQDomElement viewEl = domDoc.createElement("projectview"); viewEl.setAttribute("name", it.key()); el->appendChild(viewEl); for (FileInfoList::ConstIterator it2 = it.data().constBegin(); it2 != it.data().constEnd(); ++it2) { TQDomElement urlEl = domDoc.createElement("file"); if (m_projectBase.isParentOf((*it2).url)) urlEl.setAttribute("url", KURL::relativeURL(m_projectBase, (*it2).url)); else urlEl.setAttribute("url", (*it2).url.url()); urlEl.setAttribute("line", (*it2).line); urlEl.setAttribute("col", (*it2).col); urlEl.setAttribute("encoding", (*it2).encoding); viewEl.appendChild(urlEl); } } // write the default view TQDomElement defaultEl = domDoc.createElement("defaultview"); defaultEl.setAttribute("name", m_defaultProjectView); el->appendChild(defaultEl); } void ProjectviewPart::init() { // delayed initialization stuff goes here // create the toolview m_widget = new TQWidget(0, "filelist widget"); m_widget->setIcon( SmallIcon(info()->icon()) ); m_widget->setCaption(i18n("File List")); TQBoxLayout * l = new TQVBoxLayout(m_widget); // create the toolbar if needed if (m_guibuilder) { m_toolbarWidget->reparent(m_widget, TQPoint(0, 0), true); l->addWidget(m_toolbarWidget); TQWhatsThis::add(m_toolbarWidget, i18n("View Session Toolbar

This allows to create and work with view sessions. A view session is a set of open documents.

")); } // create the listview TQWidget * fileListWidget = new FileListWidget(this, m_widget); fileListWidget->setCaption(i18n("File List")); TQWhatsThis::add(fileListWidget, i18n("File List

This is the list of opened files.

")); l->addWidget(fileListWidget); m_widget->setFocusProxy(fileListWidget); mainWindow()->embedSelectView(m_widget, i18n("File List"), i18n("Open files")); if (!project()) readConfig(); } void ProjectviewPart::setupActions() { m_openPrjViewAction = new KSelectAction(i18n("Open Session..."), 0, actionCollection(), "viewsession_open"); connect(m_openPrjViewAction, TQT_SIGNAL(activated(const TQString &)), this, TQT_SLOT(slotOpenProjectView(const TQString &))); m_openPrjViewAction->setToolTip(i18n("Open Session")); m_savePrjViewAction = new KAction(i18n("Save Session"), "filesave", 0, this, TQT_SLOT(slotSaveProjectView()), actionCollection(), "viewsession_save"); m_newPrjViewAction = new KAction(i18n("New Session..."), "filenew", 0, this, TQT_SLOT(slotSaveAsProjectView()), actionCollection(), "viewsession_new"); m_deletePrjViewAction = new KSelectAction(i18n("Delete Session"), "editdelete", 0, actionCollection(), "viewsession_delete"); connect(m_deletePrjViewAction, TQT_SIGNAL(activated(const TQString &)), this, TQT_SLOT(slotDeleteProjectView(const TQString &))); m_deletePrjViewAction->setToolTip(i18n("Delete Session")); m_deleteCurrentPrjViewAction = new KAction(i18n("Delete Session"), "editdelete", 0, this, TQT_SLOT(slotDeleteProjectViewCurent()), actionCollection(), "viewsession_deletecurrent"); m_deleteCurrentPrjViewAction->setToolTip(i18n("Delete Session")); adjustViewActions(); } void ProjectviewPart::insertConfigWidget(const KDialogBase *dlg, TQWidget *page, unsigned int pageNo) { // create configuraton dialogs here switch (pageNo) { case PROJECTDOC_OPTIONS: { ProjectviewProjectConfig *w = new ProjectviewProjectConfig(this, page, "project config"); connect(dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept())); break; } case GLOBALDOC_OPTIONS: { ProjectviewConfig *w = new ProjectviewConfig(page, "global config"); connect(dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept())); break; } } } void ProjectviewPart::contextMenu(TQPopupMenu */*popup*/, const Context */*context*/) { // put actions into the context menu here // if (context->hasType(Context::EditorContext)) // { // // editor context menu // const EditorContext *econtext = static_cast(context); // // // use context and plug actions here // // action->plug(popup); // // // or create menu items on the fly // // int id = -1; // // id = popup->insertItem(i18n("Do Something Here"), // // this, TQT_SLOT(doSomething())); // // popup->setWhatsThis(id, i18n("Do something here

Describe here what does this action do." // } // else if (context->hasType(Context::FileContext)) // { // // file context menu // const FileContext *fcontext = static_cast(context); // // //use context and plug actions here // } // else if (context->hasType(Context::ProjectModelItemContext)) // { // // project tree context menu // const ProjectModelItemContext *pcontext = static_cast(context); // // // use context and plug actions here // } // else if (context->hasType(Context::CodeModelItemContext)) // { // // class tree context menu // const CodeModelItemContext *mcontext = static_cast(context); // // // use context and plug actions here // } // else if (context->hasType(Context::DocumentationContext)) // { // // documentation viewer context menu // const DocumentationContext *dcontext = static_cast(context); // // // use context and plug actions here // } } void ProjectviewPart::projectOpened() { if ( !m_restored ) m_projectViews.clear(); // remove the global views adjustViewActions(); m_restored = false; } void ProjectviewPart::projectClosed() { m_projectBase = KURL(); m_defaultProjectView = ""; readConfig(); // read the global project views } void ProjectviewPart::slotOpenProjectView(const TQString &view) { KConfig * config = kapp->config(); config->setGroup("File List Plugin"); bool onlyProject = config->readBoolEntry("OnlyProjectFiles", false); bool closeOpenFiles = config->readBoolEntry("CloseOpenFiles", true); m_currentProjectView = view; if (m_projectViews.contains(view) > 0) { FileInfoList viewUrls = m_projectViews[view]; if (closeOpenFiles) { // we close everything that is not part of the project view KURL::List urlsToClose = partController()->openURLs(); for (KURL::List::Iterator it = urlsToClose.begin(); it != urlsToClose.end(); ++it) { // it is in the list of wanted files and do we want it at all if ((viewUrls.contains(*it) > 0) && (!onlyProject || !project() || project()->isProjectFile((*it).path()) )) { viewUrls.remove(*it); // don't open if it is open already it = urlsToClose.remove(it); --it; // do not skip one } } if (!urlsToClose.empty()) { partController()->closeFiles(urlsToClose); } } // we open what still needs to get opened FileInfoList::const_iterator viewIt; for (viewIt = viewUrls.begin(); viewIt != viewUrls.end(); ++viewIt) { if (!onlyProject || !project() || project()->isProjectFile((*viewIt).url.path())) { partController()->setEncoding( (*viewIt).encoding ); partController()->editDocument((*viewIt).url, (*viewIt).line, (*viewIt).col); } } } adjustViewActions(); } void ProjectviewPart::slotSaveProjectView() { slotSaveAsProjectView(m_currentProjectView.isEmpty()); } void ProjectviewPart::adjustViewActions() { TQStringList viewList = getViewList(); m_openPrjViewAction->clear(); m_openPrjViewAction->setItems(viewList); int i = viewList.findIndex(m_currentProjectView); if (i > -1) { m_openPrjViewAction->setCurrentItem(i); } m_deletePrjViewAction->clear(); m_deletePrjViewAction->setItems(viewList); m_currentProjectView = m_openPrjViewAction->currentText(); if (m_currentProjectView.isEmpty() && !viewList.empty()) { m_currentProjectView = viewList.front(); } bool haveView = !m_currentProjectView.isEmpty(); m_savePrjViewAction->setEnabled(haveView); m_deleteCurrentPrjViewAction->setEnabled(haveView); } void ProjectviewPart::slotDeleteProjectViewCurent() { slotDeleteProjectView(m_currentProjectView); } void ProjectviewPart::slotDeleteProjectView(const TQString& view) { m_projectViews.remove(view); if (m_currentProjectView == view) m_currentProjectView = ""; if (m_defaultProjectView == view) m_defaultProjectView = ""; if (! project()) writeConfig(); adjustViewActions(); } void ProjectviewPart::slotSaveAsProjectView(bool askForName) { if (askForName) { bool ok; TQString newProjectView = KInputDialog::getText(i18n("Save View Session As"), i18n("Enter the name of the session:"), "", &ok, mainWindow()->main()); if (!ok) { return; } newProjectView = newProjectView.remove("="); // we use this string in config files and = would confuse it if (m_projectViews.contains(newProjectView) > 0 && KMessageBox::warningContinueCancel(mainWindow()->main(), i18n("A view session named %1 already exists.
Do you want to overwrite it?
").tqarg(newProjectView), TQString(), i18n("Overwrite")) != KMessageBox::Continue) { return; } m_currentProjectView = newProjectView; } FileInfoList viewUrls; KURL::List openURLs = partController()->openURLs(); for (KURL::List::Iterator it = openURLs.begin(); it != openURLs.end(); ++it) { // test if we have an editor // FIXME this can fail if there are two parts with the same URL KParts::ReadOnlyPart *ro_part = partController()->partForURL(*it); KTextEditor::ViewCursorInterface* cursorIf = dynamic_cast(ro_part->widget()); if (cursorIf) { TQString encoding; if ( KTextEditor::EncodingInterface * ei = dynamic_cast( ro_part ) ) { TQString temp = ei->encoding(); if ( !temp.isNull() ) { encoding = temp; } } unsigned int line, col; cursorIf->cursorPositionReal(&line, &col); viewUrls.append(FileInfo(*it, line, col, encoding)); } } // add or overwrite the values m_projectViews.insert(m_currentProjectView, viewUrls, true); if (! project()) writeConfig(); adjustViewActions(); } void ProjectviewPart::writeConfig() { KConfig * config = kapp->config(); config->deleteGroup("ProjectViews", true); config->setGroup("ProjectViews"); // write all views ViewMap::ConstIterator it; for (it = m_projectViews.constBegin(); it != m_projectViews.constEnd(); ++it) { // we create the view even if there is no file inside, might be wanted by the user TQStringList urls; for (FileInfoList::ConstIterator it2 = it.data().constBegin(); it2 != it.data().constEnd(); ++it2) { if ((*it2).encoding.isEmpty()) urls.append((*it2).url.url()); else urls.append((*it2).url.url() + ";" + (*it2).encoding); } config->writeEntry(it.key(), urls); } } void ProjectviewPart::readConfig() { KConfig * config = kapp->config(); TQMap entries = config->entryMap("ProjectViews"); m_projectViews.clear(); TQMap::ConstIterator it; for (it = entries.constBegin(); it != entries.constEnd(); ++it) { FileInfoList urlList; TQStringList urls = TQStringList::split(",", it.data()); for (TQStringList::Iterator it2 = urls.begin(); it2 != urls.end(); ++it2 ) { // search the encoding. The entry can be like: fileURL;encoding TQStringList file = TQStringList::split(";", *it2); if (file.count() == 1) urlList.append(FileInfo(KURL::fromPathOrURL(*it2))); else urlList.append(FileInfo(KURL::fromPathOrURL(file.first()), -1, -1, file.last())); } m_projectViews.insert(it.key(), urlList); } adjustViewActions(); } #include "projectviewpart.moc"