diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch) | |
tree | acaf47eb0fa12142d3896416a69e74cbf5a72242 /parts/fileview | |
download | tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'parts/fileview')
30 files changed, 3804 insertions, 0 deletions
diff --git a/parts/fileview/Makefile.am b/parts/fileview/Makefile.am new file mode 100644 index 00000000..7cc33aa6 --- /dev/null +++ b/parts/fileview/Makefile.am @@ -0,0 +1,26 @@ +# Here resides the file view part. + +INCLUDES = -I$(top_srcdir)/lib/compat -I$(top_srcdir)/lib/interfaces \ + -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/util $(all_includes) + +kde_module_LTLIBRARIES = libkdevfileview.la libkdevfilegroups.la + +libkdevfileview_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkdevfileview_la_LIBADD = $(top_builddir)/lib/libkdevelop.la + +libkdevfilegroups_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkdevfilegroups_la_LIBADD = $(top_builddir)/lib/libkdevelop.la + +libkdevfileview_la_SOURCES = fileviewpart.cpp filetreewidget.cpp partwidget.cpp vcscolorsconfigwidgetbase.ui vcscolorsconfigwidget.cpp stdfiletreewidgetimpl.cpp filetreeviewwidgetimpl.cpp vcsfiletreewidgetimpl.cpp fileitemfactory.cpp + +libkdevfilegroups_la_SOURCES = filegroupswidget.cpp addfilegroupdlg.cpp filegroupsconfigwidget.cpp filegroupsconfigwidgetbase.ui filegroupspart.cpp + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir) +service_DATA = kdevfileview.desktop kdevfilegroups.desktop + +# not used currently +#rcdir = $(kde_datadir)/kdevfileview +#rc_DATA = kdevfileview.rc +noinst_HEADERS = vcscolorsconfigwidget.h stdfiletreewidgetimpl.h filetreeviewwidgetimpl.h vcsfiletreewidgetimpl.h fileitemfactory.h diff --git a/parts/fileview/README.dox b/parts/fileview/README.dox new file mode 100644 index 00000000..d8143dd1 --- /dev/null +++ b/parts/fileview/README.dox @@ -0,0 +1,53 @@ +/** \class FileViewPart +The file tree list view for displaying files within project dir. + +\authors <a href="mailto:bernd AT kdevelop.org">Bernd Gehrmann</a> + +\maintainer <a href="mailto:mario.scalas AT libero.it">Mario Scalas</a> + +\feature Provides a way of navigating and interacting with the source files of the current project. + +\bug bugs in <a href="http://bugs.kde.org/buglist.cgi?product=kdevelop&component=file+tree&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=Bug+Number">file tree component at Bugzilla database</a> +\bug Describe a the 1st bug that you know of, but probably hasn't been reported yet. +.. +\bug Describe a the nth bug that you know of, but probably hasn't been reported yet. + +\requirement Describe a the 1st requirement of your part. +\requirement Describe a the 2nd requirement of your part. +... +\requirement Describe a the nth requirement of your part. + +\todo Describe a the 1st TODO of your part. +\todo Describe a the 2nd TODO of your part. +... +\todo Describe a the nth TODO of your part. + +\faq <b>First frequenly asked question about your part ?</b> Answer. +\faq <b>Second frequenly asked question about your part ?</b> Answer. +... +\faq <b>Last frequenly asked question about your part ?</b> Answer. + +\note First note text. +\note Second note text. +... +\note Last note text. + +\warning First warning text. +\warning Second warning text. +... +\warning Last warning text. + +*/ + +/** \class FileGroupsPart +Allows grouping of project files according to filename patterns. + +\authors <a href="mailto:bernd AT kdevelop.org">Bernd Gehrmann</a> + +\maintainer <a href="mailto:mario.scalas AT libero.it">Mario Scalas</a> + +\feature Provides a way of navigating and interacting with the source files (grouped by extension type) of the current project. + +\bug bugs in <a href="http://bugs.kde.org/buglist.cgi?product=kdevelop&component=File+Groups&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=Bug+Number">file groups component at Bugzilla database</a> + +*/ diff --git a/parts/fileview/addfilegroupdlg.cpp b/parts/fileview/addfilegroupdlg.cpp new file mode 100644 index 00000000..ef194da1 --- /dev/null +++ b/parts/fileview/addfilegroupdlg.cpp @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2001 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <kbuttonbox.h> +#include <klocale.h> +#include <kstdguiitem.h> +#include <kdeversion.h> + +#include "addfilegroupdlg.h" + + +AddFileGroupDialog::AddFileGroupDialog(const QString& old_title, const QString& old_pattern, QWidget *parent, const char *name) + : QDialog(parent, name, true) +{ + QLabel *title_label = new QLabel(i18n("&Title:"), this); + title_edit = new KLineEdit(old_title, this); + title_edit->setFocus(); + title_label->setBuddy(title_edit); + connect( title_edit, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotTextChanged() ) ); + + QLabel *pattern_label = new QLabel(i18n("&Pattern:"), this); + pattern_edit = new KLineEdit(old_pattern, this); + pattern_label->setBuddy(pattern_edit); + QFontMetrics fm(pattern_edit->fontMetrics()); + pattern_edit->setMinimumWidth(fm.width('X')*35); + connect( pattern_edit, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotTextChanged() ) ); + QVBoxLayout *layout = new QVBoxLayout(this, 10); + + QGridLayout *grid = new QGridLayout(2, 2); + layout->addLayout(grid); + grid->addWidget(title_label, 0, 0); + grid->addWidget(title_edit, 0, 1); + grid->addWidget(pattern_label, 1, 0); + grid->addWidget(pattern_edit, 1, 1); + + QFrame *frame = new QFrame(this); + frame->setFrameStyle(QFrame::HLine | QFrame::Sunken); + layout->addWidget(frame, 0); + + KButtonBox *buttonbox = new KButtonBox(this); + buttonbox->addStretch(); + m_pOk = buttonbox->addButton(KStdGuiItem::ok()); + QPushButton *cancel = buttonbox->addButton(KStdGuiItem::cancel()); + + m_pOk->setDefault(true); + connect( m_pOk, SIGNAL(clicked()), this, SLOT(accept()) ); + connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) ); + buttonbox->layout(); + layout->addWidget(buttonbox, 0); + slotTextChanged(); +} + + +AddFileGroupDialog::~AddFileGroupDialog() +{} + +void AddFileGroupDialog::slotTextChanged() +{ + m_pOk->setEnabled( !title_edit->text().isEmpty() && !pattern_edit->text().isEmpty() ); +} + +#include "addfilegroupdlg.moc" diff --git a/parts/fileview/addfilegroupdlg.h b/parts/fileview/addfilegroupdlg.h new file mode 100644 index 00000000..f72a2007 --- /dev/null +++ b/parts/fileview/addfilegroupdlg.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2001 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _ADDFILEGROUPDLG_H_ +#define _ADDFILEGROUPDLG_H_ + +#include <qdialog.h> +#include <klineedit.h> +class QPushButton; + +class AddFileGroupDialog : public QDialog +{ + Q_OBJECT + +public: + AddFileGroupDialog( const QString& old_title="", const QString& old_pattern="", QWidget *parent=0, const char *name=0 ); + ~AddFileGroupDialog(); + + QString title() const + { return title_edit->text(); } + QString pattern() const + { return pattern_edit->text(); } + private slots: + void slotTextChanged(); +private: + KLineEdit *title_edit; + KLineEdit *pattern_edit; + QPushButton *m_pOk; +}; + +#endif diff --git a/parts/fileview/filegroupsconfigwidget.cpp b/parts/fileview/filegroupsconfigwidget.cpp new file mode 100644 index 00000000..28a0441b --- /dev/null +++ b/parts/fileview/filegroupsconfigwidget.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include "filegroupsconfigwidget.h" + +#include <qlistview.h> +#include <knotifyclient.h> +#include <klocale.h> + +#include "domutil.h" +#include "addfilegroupdlg.h" +#include "filegroupspart.h" + + +FileGroupsConfigWidget::FileGroupsConfigWidget(FileGroupsPart *part, + QWidget *parent, const char *name) + : FileGroupsConfigWidgetBase(parent, name) +{ + m_part = part; + + listview->setSorting(-1); + + readConfig(); +} + + +FileGroupsConfigWidget::~FileGroupsConfigWidget() +{} + + +void FileGroupsConfigWidget::readConfig() +{ + QDomDocument &dom = *m_part->projectDom(); + DomUtil::PairList list = DomUtil::readPairListEntry(dom, "/kdevfileview/groups", + "group", "name", "pattern"); + + QListViewItem *lastItem = 0; + + DomUtil::PairList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + QListViewItem *newItem = new QListViewItem(listview, (*it).first, (*it).second); + if (lastItem) + newItem->moveItem(lastItem); + lastItem = newItem; + } +} + + +void FileGroupsConfigWidget::storeConfig() +{ + DomUtil::PairList list; + + QListViewItem *item = listview->firstChild(); + while (item) { + list << DomUtil::Pair(item->text(0), item->text(1)); + item = item->nextSibling(); + } + + DomUtil::writePairListEntry(*m_part->projectDom(), "/kdevfileview/groups", + "group", "name", "pattern", list); +} + + +void FileGroupsConfigWidget::addGroup() +{ + AddFileGroupDialog dlg; + dlg.setCaption(i18n("Add File Group")); + if (!dlg.exec()) + return; + + (void) new QListViewItem(listview, dlg.title(), dlg.pattern()); +} + + +void FileGroupsConfigWidget::editGroup() +{ + if (listview->childCount()==0 || listview->currentItem()==0) + return; + AddFileGroupDialog dlg(listview->currentItem()->text(0),listview->currentItem()->text(1)); + dlg.setCaption(i18n("Edit File Group")); + if (!dlg.exec() || dlg.title().isEmpty() || dlg.pattern().isEmpty()) + return; + listview->currentItem()->setText(0,dlg.title()); + listview->currentItem()->setText(1,dlg.pattern()); +} + + +void FileGroupsConfigWidget::removeGroup() +{ + delete listview->currentItem(); +} + + +void FileGroupsConfigWidget::moveUp() +{ + if (listview->currentItem() == listview->firstChild()) { + KNotifyClient::beep(); + return; + } + + QListViewItem *item = listview->firstChild(); + while (item->nextSibling() != listview->currentItem()) + item = item->nextSibling(); + item->moveItem(listview->currentItem()); +} + + +void FileGroupsConfigWidget::moveDown() +{ + if (listview->currentItem()->nextSibling() == 0) { + KNotifyClient::beep(); + return; + } + + listview->currentItem()->moveItem(listview->currentItem()->nextSibling()); +} + + +void FileGroupsConfigWidget::accept() +{ + storeConfig(); + m_part->refresh(); +} + +#include "filegroupsconfigwidget.moc" diff --git a/parts/fileview/filegroupsconfigwidget.h b/parts/fileview/filegroupsconfigwidget.h new file mode 100644 index 00000000..b9b5c574 --- /dev/null +++ b/parts/fileview/filegroupsconfigwidget.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILEGROUPSCONFIGWIDGET_H_ +#define _FILEGROUPSCONFIGWIDGET_H_ + +#include "filegroupsconfigwidgetbase.h" + +class FileGroupsPart; + + +class FileGroupsConfigWidget : public FileGroupsConfigWidgetBase +{ + Q_OBJECT + +public: + FileGroupsConfigWidget( FileGroupsPart *widget, QWidget *parent, const char *name=0 ); + ~FileGroupsConfigWidget(); + +public slots: + void accept(); + +private: + virtual void addGroup(); + virtual void editGroup(); + virtual void removeGroup(); + virtual void moveUp(); + virtual void moveDown(); + + void readConfig(); + void storeConfig(); + + FileGroupsPart *m_part; +}; + +#endif diff --git a/parts/fileview/filegroupsconfigwidgetbase.ui b/parts/fileview/filegroupsconfigwidgetbase.ui new file mode 100644 index 00000000..3b548458 --- /dev/null +++ b/parts/fileview/filegroupsconfigwidgetbase.ui @@ -0,0 +1,229 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>FileGroupsConfigWidgetBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>filegroups_config_widget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>599</width> + <height>496</height> + </rect> + </property> + <property name="caption"> + <string>File Group View</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>title_label</cstring> + </property> + <property name="text"> + <string>&Groups in the file view and their corresponding patterns:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>listview</cstring> + </property> + </widget> + <widget class="QListView"> + <column> + <property name="text"> + <string>Group</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Pattern</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>listview</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>addgroup_button</cstring> + </property> + <property name="text"> + <string>&Add Group...</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>editgroup_button</cstring> + </property> + <property name="text"> + <string>&Edit Group...</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>deletegroup_button</cstring> + </property> + <property name="text"> + <string>De&lete Group</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>moveup_button</cstring> + </property> + <property name="text"> + <string>Move &Up</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>movedown_button</cstring> + </property> + <property name="text"> + <string>Move &Down</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </hbox> +</widget> +<connections> + <connection> + <sender>moveup_button</sender> + <signal>clicked()</signal> + <receiver>filegroups_config_widget</receiver> + <slot>moveUp()</slot> + </connection> + <connection> + <sender>deletegroup_button</sender> + <signal>clicked()</signal> + <receiver>filegroups_config_widget</receiver> + <slot>removeGroup()</slot> + </connection> + <connection> + <sender>addgroup_button</sender> + <signal>clicked()</signal> + <receiver>filegroups_config_widget</receiver> + <slot>addGroup()</slot> + </connection> + <connection> + <sender>editgroup_button</sender> + <signal>clicked()</signal> + <receiver>filegroups_config_widget</receiver> + <slot>editGroup()</slot> + </connection> + <connection> + <sender>movedown_button</sender> + <signal>clicked()</signal> + <receiver>filegroups_config_widget</receiver> + <slot>moveDown()</slot> + </connection> +</connections> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<slots> + <slot access="protected">addGroup()</slot> + <slot access="protected">editGroup()</slot> + <slot access="protected">removeGroup()</slot> + <slot access="protected">moveUp()</slot> + <slot access="protected">moveDown()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/parts/fileview/filegroupspart.cpp b/parts/fileview/filegroupspart.cpp new file mode 100644 index 00000000..1c6a5abf --- /dev/null +++ b/parts/fileview/filegroupspart.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include "filegroupspart.h" +#include "filegroupspart.moc" + +#include <qwhatsthis.h> +#include <qvbox.h> +#include <qtimer.h> +#include <kaction.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kdevgenericfactory.h> +#include <kdialogbase.h> + +#include "kdevcore.h" +#include "kdevproject.h" +#include "kdevmainwindow.h" +#include "kdevplugininfo.h" + +#include "filegroupswidget.h" +#include "filegroupsconfigwidget.h" + +#define FILEGROUPS_OPTIONS 1 + +typedef KDevGenericFactory<FileGroupsPart> FileGroupsFactory; +static const KDevPluginInfo data("kdevfilegroups"); +K_EXPORT_COMPONENT_FACTORY( libkdevfilegroups, FileGroupsFactory( data ) ) + +FileGroupsPart::FileGroupsPart(QObject *parent, const char *name, const QStringList &) + : KDevPlugin(&data, parent, name ? name : "FileGroupsPart") +{ + deleteRequested = false; + setInstance(FileGroupsFactory::instance()); + + m_filegroups = new FileGroupsWidget(this); + m_filegroups->setCaption(i18n("File Group View")); + m_filegroups->setIcon(SmallIcon( info()->icon() ) ); + QWhatsThis::add(m_filegroups, i18n("<b>File group view</b><p>" + "The file group viewer shows all files of the project, " + "in groups which can be configured in project settings dialog, <b>File Groups</b> tab.")); + mainWindow()->embedSelectView(m_filegroups, i18n("File Groups"), i18n("File groups in the project directory")); + + _configProxy = new ConfigWidgetProxy( core() ); + _configProxy->createProjectConfigPage( i18n("File Groups"), FILEGROUPS_OPTIONS, info()->icon() ); + connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), + this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) ); + + + // File groups + connect( project(), SIGNAL(addedFilesToProject(const QStringList&)), + m_filegroups, SLOT(addFiles(const QStringList&)) ); + connect( project(), SIGNAL(removedFilesFromProject(const QStringList&)), + m_filegroups, SLOT(removeFiles(const QStringList&)) ); +/* connect( project(), SIGNAL(addedFileToProject(const QString&)), + m_filegroups, SLOT(addFile(const QString&)) ); + connect( project(), SIGNAL(removedFileFromProject(const QString&)), + m_filegroups, SLOT(removeFile(const QString&)) );*/ + m_filegroups->refresh(); +} + +FileGroupsPart::~FileGroupsPart() +{ + deleteRequested = true; + if (m_filegroups) + mainWindow()->removeView(m_filegroups); + delete m_filegroups; + delete _configProxy; +} + +void FileGroupsPart::refresh() +{ + if (deleteRequested) + return; + // This method may be called from m_filetree's slot, + // so we make sure not to modify the list view during + // the execution of the slot + QTimer::singleShot(0, m_filegroups, SLOT(refresh())); +} + +void FileGroupsPart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber ) +{ + if ( pagenumber == FILEGROUPS_OPTIONS ) + { + FileGroupsConfigWidget *w = new FileGroupsConfigWidget(this, page, "file groups config widget"); + connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) ); + } +} diff --git a/parts/fileview/filegroupspart.h b/parts/fileview/filegroupspart.h new file mode 100644 index 00000000..8e712b4b --- /dev/null +++ b/parts/fileview/filegroupspart.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILEGROUPSPART_H_ +#define _FILEGROUPSPART_H_ + +#include <qguardedptr.h> +//#include <kdialogbase.h> +#include <configwidgetproxy.h> +#include "kdevplugin.h" + +class FileGroupsWidget; +class KDialogBase; + +class FileGroupsPart : public KDevPlugin +{ + Q_OBJECT + +public: + FileGroupsPart( QObject *parent, const char *name, const QStringList & ); + ~FileGroupsPart(); + +public slots: + void refresh(); + +private slots: + void insertConfigWidget( const KDialogBase* dlg, QWidget * page, unsigned int ); + +private: + QGuardedPtr<FileGroupsWidget> m_filegroups; + bool deleteRequested; + ConfigWidgetProxy * _configProxy; +}; + +#endif diff --git a/parts/fileview/filegroupswidget.cpp b/parts/fileview/filegroupswidget.cpp new file mode 100644 index 00000000..9f32460d --- /dev/null +++ b/parts/fileview/filegroupswidget.cpp @@ -0,0 +1,442 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include "filegroupswidget.h" + +#include <qfileinfo.h> +#include <qdir.h> +#include <qheader.h> +#include <qtimer.h> +#include <qvbox.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kdialogbase.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include <kdeversion.h> + +#include "kdevcore.h" +#include "kdevproject.h" +#include "kdevmainwindow.h" +#include "kdevpartcontroller.h" +#include "domutil.h" + +#include "filegroupspart.h" +#include "filegroupsconfigwidget.h" + + +// Translations for strings in the project file +static const char *translations[] = { + I18N_NOOP("Sources"), + I18N_NOOP("Translations"), + I18N_NOOP("User Interface"), + I18N_NOOP("Others") +}; + +class FileComparator { +public: + virtual ~FileComparator(){ + }; + virtual bool matches(const QString& name) const = 0; +}; + +class RegExpComparator : public FileComparator { +public: + RegExpComparator(const QString& pattern) : m_exp(pattern, true, true){ + } + bool matches(const QString& name) const{ + return m_exp.exactMatch(name); + } +private: + const QRegExp m_exp; +}; + +class EndingComparator : public FileComparator { +public: + EndingComparator(const QString& pattern) : m_pattern ( pattern){ + } + bool matches(const QString& name) const{ + return name.endsWith(m_pattern); + } +private: + const QString m_pattern; +}; + +class FileViewFolderItem : public QListViewItem +{ +public: + FileViewFolderItem(QListView *parent, const QString &name, const QString &pattern); + bool matches(const QString &fileName); + +private: + QPtrList<FileComparator> m_patterns; +}; + + +FileViewFolderItem::FileViewFolderItem(QListView *parent, const QString &name, const QString &pattern) + : QListViewItem(parent, name) +{ + setPixmap(0, SmallIcon("folder")); + m_patterns.setAutoDelete(true); + QStringList patternstring = QStringList::split(';', pattern); + QStringList::ConstIterator theend = patternstring.end(); + for (QStringList::ConstIterator ci = patternstring.begin(); ci != theend; ++ci) + { + QString pattern = *ci; + QString tail = pattern.right( pattern.length() - 1 ); + + if ( (tail).contains('*') || pattern.contains('?') || pattern.contains('[') || pattern.contains(']') ) + { + m_patterns.append( new RegExpComparator( pattern ) ); + } + else + { + if ( pattern.startsWith("*") ) + { + m_patterns.append( new EndingComparator( tail ) ); + } + else + { + m_patterns.append( new EndingComparator( pattern ) ); + } + } + } +} + + +bool FileViewFolderItem::matches(const QString &fileName) +{ + // Test with the file path, so that "*ClientServer/*.h" patterns work + QString fName = QFileInfo(fileName).filePath(); + + QPtrList<FileComparator>::ConstIterator theend = m_patterns.end(); + for (QPtrList<FileComparator>::ConstIterator ci = m_patterns.begin(); ci != theend; ++ci) + if ((*ci)->matches(fName)) + return true; + + return false; +} + + +class FileGroupsFileItem : public QListViewItem +{ +public: + FileGroupsFileItem(QListViewItem *parent, const QString &fileName); + QString fileName() const + { return fullname; } + +private: + QString fullname; +}; + + +FileGroupsFileItem::FileGroupsFileItem(QListViewItem *parent, const QString &fileName) + : QListViewItem(parent), fullname(fileName) +{ + setPixmap(0, SmallIcon("document")); + QFileInfo fi(fileName); + setText(0, fi.fileName()); + setText(1, "./" + fi.dirPath()); +} + +FileGroupsWidget::FileGroupsWidget(FileGroupsPart *part) + : KListView(0, "file view widget"), + m_actionToggleShowNonProjectFiles( 0 ), m_actionToggleDisplayLocation( 0 ) +{ + /* + Setting Location ID to -1 so I can check if it has been loaded later. + If I dont, it will remove the name column and this is not too good :-) + Is there any better way to do this? + */ + LocationID=-1; + + setFocusPolicy(ClickFocus); + setRootIsDecorated(true); + setResizeMode(QListView::LastColumn); + setSorting(-1); + addColumn(i18n("Name")); + setAllColumnsShowFocus( true ); + +// addColumn(i18n("Location")); + + connect( this, SIGNAL(executed(QListViewItem*)), + this, SLOT(slotItemExecuted(QListViewItem*)) ); + connect( this, SIGNAL(returnPressed(QListViewItem*)), + this, SLOT(slotItemExecuted(QListViewItem*)) ); + connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), + this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) ); + + m_actionToggleShowNonProjectFiles = new KToggleAction( i18n("Show Non Project Files"), KShortcut(), + this, SLOT(slotToggleShowNonProjectFiles()), this, "actiontoggleshowshownonprojectfiles" ); + m_actionToggleShowNonProjectFiles->setCheckedState(i18n("Hide Non Project Files")); + m_actionToggleShowNonProjectFiles->setWhatsThis(i18n("<b>Show non project files</b><p>Shows files that do not belong to a project in a file tree.")); + + m_actionToggleDisplayLocation = new KToggleAction( i18n("Display Location Column"), KShortcut(), + this, SLOT(slotToggleDisplayLocation()), this, "actiontoggleshowlocation" ); + m_actionToggleDisplayLocation->setWhatsThis(i18n("<b>Display the Location Column</b><p>Displays a column with the location of the files.")); + + m_part = part; + (void) translations; // supress compiler warning + + QDomDocument &dom = *m_part->projectDom(); + m_actionToggleShowNonProjectFiles->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonprojectfiles") ); + m_actionToggleDisplayLocation->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonlocation") ); +} + + +FileGroupsWidget::~FileGroupsWidget() +{ + QDomDocument &dom = *m_part->projectDom(); + DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonprojectfiles", !m_actionToggleShowNonProjectFiles->isChecked() ); + DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonlocation", !m_actionToggleDisplayLocation->isChecked() ); +} + + +void FileGroupsWidget::slotItemExecuted(QListViewItem *item) +{ + if (!item) + return; + + // toggle open state for parents + if (item->childCount() > 0) + setOpen(item, !isOpen(item)); + + // Is it a group item? + if (!item->parent()) + return; + + FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(item); + m_part->partController()->editDocument(KURL::fromPathOrURL( m_part->project()->projectDirectory() + "/" + fgfitem->fileName() )); +} + + +void FileGroupsWidget::slotContextMenu(KListView *, QListViewItem *item, const QPoint &p) +{ + KPopupMenu popup(i18n("File Groups"), this); + /// @todo Add, remove groups + int customizeId = popup.insertItem(i18n("Customize...")); + popup.setWhatsThis(customizeId, i18n("<b>Customize</b><p>Opens <b>Customize File Groups</b> dialog where the groups can be managed.")); + if (item) { + if (item->parent()) { + // Not for group items + FileGroupsFileItem *fvfitem = static_cast<FileGroupsFileItem*>(item); + QString pathName = m_part->project()->projectDirectory() + QDir::separator() + fvfitem->fileName(); + KURL::List urls; + urls.append(pathName); + FileContext context(urls); + m_part->core()->fillContextMenu(&popup, &context); + } + else{ + QStringList file_list; + QListViewItem* i = item->firstChild(); + while(i){ + FileGroupsFileItem *fvgitem = static_cast<FileGroupsFileItem*>(i); + file_list << fvgitem->fileName(); + i = i->nextSibling(); + } + FileContext context(file_list); + m_part->core()->fillContextMenu(&popup, &context); + } + } + m_actionToggleShowNonProjectFiles->plug( &popup ); + m_actionToggleDisplayLocation->plug( &popup ); + + int res = popup.exec(p); + if (res == customizeId) { + KDialogBase dlg(KDialogBase::TreeList, i18n("Customize File Groups"), + KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, this, + "customization dialog"); + QVBox *vbox = dlg.addVBoxPage(i18n("File Groups")); + FileGroupsConfigWidget *w = new FileGroupsConfigWidget(m_part, vbox, "file groups config widget"); + connect(&dlg, SIGNAL(okClicked()), w, SLOT(accept())); + dlg.exec(); + } +} + +QStringList FileGroupsWidget::allFilesRecursively( QString const & dir ) +{ + QStringList filelist; + QString reldir = dir.mid( m_part->project()->projectDirectory().length() +1 ); + + // recursively fetch all files in subdirectories + QStringList subdirs = QDir( dir ).entryList( QDir::Dirs ); + QValueListIterator<QString> it = subdirs.begin(); + while ( it != subdirs.end() ) + { + if ( *it != "." && *it != ".." ) + { + filelist += allFilesRecursively( dir + "/"+ *it ); + } + ++it; + } + + // append the project relative directory path to all files in the current directory + QStringList dirlist = QDir( dir ).entryList( QDir::Files ); + QValueListIterator<QString> itt = dirlist.begin(); + while ( itt != dirlist.end() ) + { + if ( reldir.isEmpty() ) + { + filelist << *itt; + } + else + { + filelist << reldir + "/" + *itt; + } + ++itt; + } + + return filelist; +} + +void FileGroupsWidget::refresh() +{ + while (firstChild()) + delete firstChild(); + + if (m_actionToggleDisplayLocation->isChecked()) { + // Display the Location column + LocationID=addColumn(i18n("Location")); + } + else { + // Remove the Location column + //Need to check if the ID exists, if not do nothing!! + if (LocationID!=-1) + removeColumn(LocationID); + } + QDomDocument &dom = *m_part->projectDom(); + DomUtil::PairList list = + DomUtil::readPairListEntry(dom, "/kdevfileview/groups", "group", "name", "pattern"); + + FileViewFolderItem *lastGroup = 0; + + DomUtil::PairList::ConstIterator git; + for (git = list.begin(); git != list.end(); ++git) { + FileViewFolderItem *newItem = new FileViewFolderItem(this, (*git).first, (*git).second); + if (lastGroup) + newItem->moveItem(lastGroup); + lastGroup = newItem; + } + + QStringList allFiles; + if (m_actionToggleShowNonProjectFiles->isChecked()) { + // get all files in the project directory + allFiles = allFilesRecursively( m_part->project()->projectDirectory() ); + } + else { + // get all project files + allFiles = m_part->project()->allFiles(); + } + QStringList::ConstIterator fit; + for (fit = allFiles.begin(); fit != allFiles.end(); ++fit) { + QListViewItem *item = firstChild(); + while (item) { + FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item); + if (fvgitem->matches(*fit)) { + (void) new FileGroupsFileItem(fvgitem, *fit); + break; + } + item = item->nextSibling(); + } + } + + QListViewItem *item = firstChild(); + while (item) { + item->sortChildItems(0, true); + item = item->nextSibling(); + } +} + + +void FileGroupsWidget::addFile(const QString &fileName) +{ + kdDebug(9017) << "FileView add " << fileName << endl; + + QListViewItem *item = firstChild(); + while (item) { + FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item); + if (fvgitem->matches(fileName)) + { + QString f = fileName; + if (fileName.contains(m_part->project()->projectDirectory())) + f = fileName.mid(m_part->project()->projectDirectory().length()+1); + (void) new FileGroupsFileItem(fvgitem, f); +// fvgitem->sortChildItems(0, true); + break; + } + item = item->nextSibling(); + } +} + +void FileGroupsWidget::addFiles ( const QStringList& fileList ) +{ + QStringList::ConstIterator it; + + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + this->addFile ( *it ); + } + sort(); +} + +void FileGroupsWidget::removeFile(const QString &fileName) +{ + kdDebug(9017) << "FileView remove " << fileName << endl; + + QListViewItem *item = firstChild(); + while (item) + { + FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item); + QListViewItem *childItem = fvgitem->firstChild(); + while (childItem) + { + FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(childItem); + kdDebug ( 9017 ) << "fvfitem->fileName() is " << fgfitem->fileName() << endl; + if (fgfitem->fileName() == fileName ) + { + kdDebug ( 9017 ) << "Deleting: " << fgfitem->fileName() << endl; + + delete fgfitem; + return; + } + childItem = childItem->nextSibling(); + } + item = item->nextSibling(); + } +} + +void FileGroupsWidget::removeFiles ( const QStringList& fileList ) +{ + QStringList::ConstIterator it; + + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + removeFile ( *it ); + } +} + +void FileGroupsWidget::slotToggleShowNonProjectFiles() +{ + refresh(); +} + +void FileGroupsWidget::slotToggleDisplayLocation() +{ + refresh(); +} + + +#include "filegroupswidget.moc" + diff --git a/parts/fileview/filegroupswidget.h b/parts/fileview/filegroupswidget.h new file mode 100644 index 00000000..7bdbf78b --- /dev/null +++ b/parts/fileview/filegroupswidget.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILEGROUPSWIDGET_H_ +#define _FILEGROUPSWIDGET_H_ + +#include <klistview.h> + +class FileGroupsPart; +class KDevProject; + + +class FileGroupsWidget : public KListView +{ + Q_OBJECT + +public: + FileGroupsWidget(FileGroupsPart *part); + ~FileGroupsWidget(); + +public slots: + void refresh(); + void addFiles ( const QStringList& fileList ); + void removeFiles ( const QStringList& fileList ); + +private slots: + void slotItemExecuted(QListViewItem *item); + void slotContextMenu(KListView *, QListViewItem *item, const QPoint &p); + void slotToggleShowNonProjectFiles(); + void slotToggleDisplayLocation(); + +protected: + void addFile(const QString &fileName); + void removeFile(const QString &fileName); + +private: + QStringList allFilesRecursively( QString const & ); + FileGroupsPart *m_part; + + class KToggleAction *m_actionToggleShowNonProjectFiles; + class KToggleAction *m_actionToggleDisplayLocation; + int LocationID; +}; + +#endif + diff --git a/parts/fileview/fileitemfactory.cpp b/parts/fileview/fileitemfactory.cpp new file mode 100644 index 00000000..614f535c --- /dev/null +++ b/parts/fileview/fileitemfactory.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include <qpainter.h> +#include <kdebug.h> + +#include "filetreewidget.h" +#include "fileitemfactory.h" + +using namespace filetreeview; + +/////////////////////////////////////////////////////////////////////////////// +// class FileTreeViewItem +/////////////////////////////////////////////////////////////////////////////// + +FileTreeWidget* FileTreeViewItem::listView() const +{ + return static_cast<FileTreeWidget*>( QListViewItem::listView() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeViewItem::hideOrShow() +{ + kdDebug( 9017 ) << "MyFileTreeViewItem::hideOrShow(): " + path() << endl; + setVisible( listView()->shouldBeShown( this ) ); + FileTreeViewItem* item = static_cast<FileTreeViewItem*>( firstChild() ); + while (item) + { + //kdDebug( 9017 ) << "MyFileTreeViewItem::hideOrShow(): " + item->path() << endl; + item->hideOrShow(); + item = static_cast<FileTreeViewItem*>( item->nextSibling() ); + } +} + +bool FileTreeViewItem::changeActiveDir( const QString& olddir, const QString& newdir, bool foundolddir, bool foundnewdir ) +{ + kdDebug( 9017 ) << "FileTreeViewItem::changeActiveDir(): " + olddir << " new: " << newdir << " for: " << path() << endl; + + if ( this->path() == olddir && isDir() && m_isActiveDir ) + { + m_isActiveDir = false; + setVisible( listView()->shouldBeShown( this ) ); + foundolddir = true; + repaint(); + } + + if ( this->path() == newdir && isDir() && !m_isActiveDir ) + { + m_isActiveDir = true; + setVisible( listView()->shouldBeShown( this ) ); + foundnewdir = true; + repaint(); + } + + if( foundnewdir && foundolddir ) + return true; + + FileTreeViewItem* item = static_cast<FileTreeViewItem*>( firstChild() ); + while( item ) + { + if ( item->changeActiveDir( olddir, newdir, foundnewdir, foundolddir ) ) + return true; + else + item = static_cast<FileTreeViewItem*>(item->nextSibling()); + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool FileTreeViewItem::setProjectFile( QString const & path, bool pf ) +{ + + if ( this->path() == path && isProjectFile() != pf ) + { + kdDebug( 9017 ) << "FileTreeViewItem::setProjectFile(): " + path << " projectfile: " << pf << endl; + m_isProjectFile = pf; + setVisible( listView()->shouldBeShown( this ) ); + repaint(); + return true; + } + + FileTreeViewItem* item = static_cast<FileTreeViewItem*>( firstChild() ); + while( item ) + { + if ( item->setProjectFile( path, pf ) ) + return true; + else + item = static_cast<FileTreeViewItem*>(item->nextSibling()); + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeViewItem::paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int alignment) +{ + if ( listView()->showNonProjectFiles() && isProjectFile() ) + { + QFont font( p->font() ); + font.setBold( true ); + p->setFont( font ); + } + + if( isActiveDir() ) + { + QFont font( p->font() ); + font.setItalic( true ); + p->setFont( font ); + } + + QListViewItem::paintCell( p, cg, column, width, alignment ); +} + + +/////////////////////////////////////////////////////////////////////////////// + +int FileTreeViewItem::compare( QListViewItem *i, int col, bool ascending ) const +{ + KFileTreeViewItem* rhs = dynamic_cast<KFileTreeViewItem*>( i ); + if (rhs) + { + if (rhs->isDir() && !isDir()) + return (ascending) ? 1 : -1; + else + if (!rhs->isDir() && isDir()) + return (ascending) ? -1 : 1; + } + + return QListViewItem::compare( i, col, ascending ); +} + +/////////////////////////////////////////////////////////////////////////////// +// class BranchItemFactory +/////////////////////////////////////////////////////////////////////////////// diff --git a/parts/fileview/fileitemfactory.h b/parts/fileview/fileitemfactory.h new file mode 100644 index 00000000..f87ae39a --- /dev/null +++ b/parts/fileview/fileitemfactory.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef FILEITEMFACTORY_H +#define FILEITEMFACTORY_H + +#include <kfiletreeview.h> + +class FileTreeWidget; + +/** +@author KDevelop Authors +*/ +namespace filetreeview +{ + /** + @author KDevelop Authors + */ + class FileTreeViewItem : public KFileTreeViewItem + { + friend class FileTreeBranchItem; + protected: + FileTreeViewItem( KFileTreeViewItem* parent, KFileItem* item, KFileTreeBranch* branch, bool pf ) + : KFileTreeViewItem( parent, item, branch ), m_isProjectFile( pf ), m_isActiveDir( false ) + { + hideOrShow(); + } + FileTreeViewItem( KFileTreeView* parent, KFileItem* item, KFileTreeBranch* branch ) + : KFileTreeViewItem( parent, item, branch ), m_isProjectFile( false ) + { + hideOrShow(); + } + virtual ~FileTreeViewItem() {} + + public: + virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ); + FileTreeWidget* listView() const; + void hideOrShow(); + bool isProjectFile() const { return m_isProjectFile; } + bool setProjectFile( QString const &path, bool pf ); + bool isActiveDir() const { return m_isActiveDir; } + bool changeActiveDir( const QString &, const QString&, bool foundolddir = false, bool foundnewdir = false ); + + protected: + virtual int compare( QListViewItem *i, int col, bool ascending ) const; + + private: + bool m_isProjectFile; + bool m_isActiveDir; + }; + + /** + @author KDevelop Authors + */ + class FileTreeBranchItem : public KFileTreeBranch + { + protected: + FileTreeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix ) + : KFileTreeBranch( view, url, name, pix, false, + new FileTreeViewItem( view, new KFileItem( url, "inode/directory", S_IFDIR ), this ) ) + { + } + virtual ~FileTreeBranchItem() + { +// if (root()) +// delete root()->fileItem(); + } + + }; + + /** + @author KDevelop Authors + */ + class BranchItemFactory + { + public: + virtual FileTreeBranchItem *makeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix ) = 0; + }; +} + +#endif diff --git a/parts/fileview/filetreeviewwidgetimpl.cpp b/parts/fileview/filetreeviewwidgetimpl.cpp new file mode 100644 index 00000000..9e40a3bb --- /dev/null +++ b/parts/fileview/filetreeviewwidgetimpl.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include <qpopupmenu.h> +#include <kxmlguiclient.h> +#include <kdebug.h> +#include <kaction.h> +#include <klocale.h> +#include <kdeversion.h> + +#include <kdevproject.h> + +#include "fileviewpart.h" +#include "filetreewidget.h" +#include "fileitemfactory.h" + +#include "filetreeviewwidgetimpl.h" + +using namespace filetreeview; + +/////////////////////////////////////////////////////////////////////////////// +// class FileTreeViewWidgetImpl +/////////////////////////////////////////////////////////////////////////////// + +FileTreeViewWidgetImpl::FileTreeViewWidgetImpl( FileTreeWidget *parent, const char *name ) + : QObject( parent, name ), m_branchItemFactory( 0 ), + m_part( parent->part() ), m_isReloadingTree( false ) +{ + kdDebug(9017) << "FileTreeViewWidgetImpl::FileTreeViewWidgetImpl()" << endl; + + // Actions + m_actionToggleShowNonProjectFiles = new KToggleAction( i18n("Show Non Project Files"), KShortcut(), + this, SLOT(slotToggleShowNonProjectFiles()), this, "actiontoggleshowshownonprojectfiles" ); + m_actionToggleShowNonProjectFiles->setCheckedState(i18n("Hide Non Project Files")); + m_actionToggleShowNonProjectFiles->setWhatsThis(i18n("<b>Show non project files</b><p>Shows files that do not belong to a project in a file tree.")); + + // Reload good ol' settings + QDomDocument &dom = *m_part->projectDom(); + m_actionToggleShowNonProjectFiles->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/tree/hidenonprojectfiles") ); +} + +/////////////////////////////////////////////////////////////////////////////// + +FileTreeViewWidgetImpl::~FileTreeViewWidgetImpl() +{ + kdDebug(9017) << "FileTreeViewWidgetImpl::~FileTreeViewWidgetImpl()" << endl; + + delete m_branchItemFactory; + + QDomDocument &dom = *m_part->projectDom(); + DomUtil::writeBoolEntry( dom, "/kdevfileview/tree/hidenonprojectfiles", !showNonProjectFiles() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +FileTreeWidget *FileTreeViewWidgetImpl::fileTree() const +{ + return static_cast<FileTreeWidget *>( parent() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +QDomDocument &FileTreeViewWidgetImpl::projectDom() const +{ + return *part()->projectDom(); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString FileTreeViewWidgetImpl::projectDirectory() const +{ + return part()->project()->projectDirectory(); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool FileTreeViewWidgetImpl::showNonProjectFiles() const +{ + return m_actionToggleShowNonProjectFiles->isChecked(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeViewWidgetImpl::fillPopupMenu( QPopupMenu *popupMenu, QListViewItem *item ) const +{ + // Show the "reload tree" menu-item only if it is requested for the root object + // and we don't have a sync-with-repository operation pending (which otherwise will + // kill the call-back's from working) + if (item == fileTree()->firstChild() && canReloadTree()) + { + int id = popupMenu->insertItem( i18n( "Reload Tree"), this, SLOT( slotReloadTree() ) ); + popupMenu->setWhatsThis( id, i18n("<b>Reload tree</b><p>Reloads the project files tree.") ); + } + + m_actionToggleShowNonProjectFiles->plug( popupMenu ); +} + +/////////////////////////////////////////////////////////////////////////////// + +KURL::List FileTreeViewWidgetImpl::selectedPathUrls() +{ + kdDebug(9017) << "FileTreeViewWidgetImpl::selectedPathUrls()" << endl; + + KURL::List urlList; + + QValueList<QListViewItem*> list = allSelectedItems( fileTree()->firstChild() ); + QValueList<QListViewItem*>::Iterator it = list.begin(); + while( it != list.end() ) + { + FileTreeViewItem * item = static_cast<FileTreeViewItem*>( *it ); + if ( fileTree()->shouldBeShown( item ) ) + { + KURL url; + url.setPath( item->path() ); + urlList << url; + } + ++it; + } + + return urlList; +} + +/////////////////////////////////////////////////////////////////////////////// + +QValueList<QListViewItem*> FileTreeViewWidgetImpl::allSelectedItems( QListViewItem * item ) const +{ + QValueList<QListViewItem*> list; + + if ( item ) + { + if ( item->isSelected() ) + { + list << item; + } + + QListViewItem * it = item->firstChild(); + while( it ) + { + list += allSelectedItems( it ); + it = it->nextSibling(); + } + } + + return list; +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeViewWidgetImpl::slotReloadTree() +{ + fileTree()->openDirectory( projectDirectory() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeViewWidgetImpl::slotToggleShowNonProjectFiles() +{ + fileTree()->hideOrShow(); +} + +#include "filetreeviewwidgetimpl.moc" diff --git a/parts/fileview/filetreeviewwidgetimpl.h b/parts/fileview/filetreeviewwidgetimpl.h new file mode 100644 index 00000000..fae4b248 --- /dev/null +++ b/parts/fileview/filetreeviewwidgetimpl.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef FILETREEVIEWWIDGETIMPL_H +#define FILETREEVIEWWIDGETIMPL_H + +#include <qobject.h> +#include <qvaluelist.h> +#include <kfiletreeview.h> +#include <qdom.h> + +#include "fileitemfactory.h" + +class FileTreeWidget; +namespace filetreeview +{ + class FileTreeViewItem; + class FileTreeBranchItem; + class BranchItemFactory; +} +class FileViewPart; +class QHeader; +class KToggleAction; +class QPopupMenu; + +/** +* @author Mario Scalas +* A base class for providing additional features to the standard KFileTreeViewItem-based widget we +* use for listing files in project directory. +*/ +class FileTreeViewWidgetImpl : public QObject +{ + Q_OBJECT +public: + FileTreeViewWidgetImpl( FileTreeWidget *parent, const char *name ); + virtual ~FileTreeViewWidgetImpl(); + + //! return a list containing the filenames of the currently selected items. + KURL::List selectedPathUrls(); + // shortcuts + FileTreeWidget *fileTree() const; + QDomDocument &projectDom() const; + QHeader *header() const { return fileTree()->header(); } + void setColumnWidth( int column, int w ) { fileTree()->setColumnWidth( column, w ); } + int contentsWidth() const { return fileTree()->contentsWidth(); } + void triggerUpdate() { fileTree()->triggerUpdate(); } + FileViewPart *part() const { return m_part; } + filetreeview::FileTreeViewItem *currentItem() const { return static_cast<filetreeview::FileTreeViewItem*>( fileTree()->currentItem() ); } + /** + * @return a reference to a new filetreeview::BranchItemFactory object which can be used for filling + * the tree view. + */ + filetreeview::BranchItemFactory *branchItemFactory() const { return m_branchItemFactory; } + /** + * Costraints that must be satisfied to start a reload of the the tree. + * @return + */ + virtual bool canReloadTree() const = 0; + /** + * Here the popup menu is filled: by standard only the "reload tree" (only if the above function + * returns true) and "show project files" options are added + * @param popupMenu the menu to fill + * @param item the QListViewItem which this menu has been requested upon + */ + virtual void fillPopupMenu( QPopupMenu *popupMenu, QListViewItem *item ) const; + /** + * @return true if non project files are to be shown, false otherwise + */ + bool showNonProjectFiles() const; + +signals: + /** + * Emitted when the current implementation "recognizes" it cannot work anymore: for example the VCS impl. + * can ask to be relieved from work when the VCS plug-in it uses has been unloaded! + */ + void implementationInvalidated(); + +private slots: + void slotReloadTree(); + void slotToggleShowNonProjectFiles(); + +protected: + void setBranchItemFactory( filetreeview::BranchItemFactory *aFactory ) { m_branchItemFactory = aFactory; } + QString projectDirectory() const; + +private: + QValueList<QListViewItem*> allSelectedItems( QListViewItem * item ) const; + filetreeview::BranchItemFactory *m_branchItemFactory; + + FileViewPart *m_part; + + bool m_isReloadingTree; + + KToggleAction *m_actionToggleShowNonProjectFiles; +}; + +#endif diff --git a/parts/fileview/filetreewidget.cpp b/parts/fileview/filetreewidget.cpp new file mode 100644 index 00000000..e0d7538b --- /dev/null +++ b/parts/fileview/filetreewidget.cpp @@ -0,0 +1,387 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * Copyright (C) 2003 by Mario Scalas (VCS Support) * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include "filetreewidget.h" + +#include <qheader.h> +#include <qpainter.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qcolor.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kfileitem.h> +#include <kurl.h> +#include <kaction.h> + +#include "kdevcore.h" +#include "kdevproject.h" +#include "kdevpartcontroller.h" +#include "kdevmainwindow.h" +#include "kdevversioncontrol.h" +#include "domutil.h" +#include "urlutil.h" + +#include "fileviewpart.h" +#include "fileitemfactory.h" +#include "vcsfiletreewidgetimpl.h" +#include "stdfiletreewidgetimpl.h" + +using namespace filetreeview; + +/////////////////////////////////////////////////////////////////////////////// +// class FileTreeViewItem +/////////////////////////////////////////////////////////////////////////////// + +#include <kdeversion.h> + +/////////////////////////////////////////////////////////////////////////////// +// class FileTreeWidget +/////////////////////////////////////////////////////////////////////////////// + +FileTreeWidget::FileTreeWidget( FileViewPart *part, QWidget *parent, KDevVCSFileInfoProvider *infoProvider ) + : KFileTreeView( parent, "filetreewidget" ), m_part( part ), m_rootBranch( 0 ) +{ + kdDebug(9017) << "Requested FileTree for: " << projectDirectory() << endl; + if (versionControl() && infoProvider) + kdDebug(9017) << "Valid VCS directory: " << versionControl()->isValidDirectory( projectDirectory() ) << endl; + + if (infoProvider && versionControl() && versionControl()->isValidDirectory( projectDirectory() )) + m_impl = new VCSFileTreeWidgetImpl( this, infoProvider ); + else + m_impl = new StdFileTreeWidgetImpl( this ); + + //setResizeMode( QListView::LastColumn ); + setSorting( 0 ); + setAllColumnsShowFocus( true ); + setSelectionMode( QListView::Extended ); // Enable multiple items selection by use of Ctrl/Shift + setDragEnabled( false ); + + // Slot connections + connect( this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotItemExecuted(QListViewItem*)) ); + connect( this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotItemExecuted(QListViewItem*)) ); + connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), + this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) ); + // Intercepts KDevelop core signals and VCS notifications (if available) + connect( m_part->project(), SIGNAL( activeDirectoryChanged( const QString&, const QString& ) ), + this, SLOT( changeActiveDirectory( const QString&, const QString& ) ) ); + connect( m_part->project(), SIGNAL( addedFilesToProject( const QStringList & ) ), + this, SLOT( addProjectFiles( const QStringList & ) ) ); + connect( m_part->project(), SIGNAL( removedFilesFromProject( const QStringList & ) ), + this, SLOT( removeProjectFiles( const QStringList & ) ) ); + // Safeguard against VCS plug-in unloading at run-time + connect( m_impl, SIGNAL(implementationInvalidated()), this, SLOT(slotImplementationInvalidated()) ); + + // Hide pattern for files + QDomDocument &dom = *m_part->projectDom(); + QString defaultHidePattern = "*.o,*.lo,CVS"; + QString hidePattern = DomUtil::readEntry( dom, "/kdevfileview/tree/hidepatterns", defaultHidePattern ); + m_hidePatterns = QStringList::split( ",", hidePattern ); +} + +/////////////////////////////////////////////////////////////////////////////// + +FileTreeWidget::~FileTreeWidget() +{ + kdDebug(9017) << "FileTreeWidget::~FileTreeWidget()" << endl; + + QDomDocument &dom = *m_part->projectDom(); + DomUtil::writeEntry( dom, "/kdevfileview/tree/hidepatterns", hidePatterns() ); + +// delete m_impl; +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::openDirectory( const QString& dirName ) +{ + kdDebug(9017) << "FileTreeWidget::openDirectory(): " + dirName << endl; + + // if we're reloading + if (m_rootBranch) + { + disconnect( m_rootBranch, SIGNAL(populateFinished(KFileTreeViewItem*)), this, SLOT(finishPopulate(KFileTreeViewItem*)) ); + removeBranch( m_rootBranch ); + m_projectFiles.clear(); + } + + addProjectFiles( m_part->project()->allFiles(), true ); + + KURL url = KURL::fromPathOrURL( dirName ); + const QPixmap& pix = KMimeType::mimeType("inode/directory")->pixmap( KIcon::Small ); + + // this is a bit odd, but the order of these calls seems to be important + //FileTreeBranch *b = new FileTreeBranch( this, url, url.prettyURL(), pix ); + FileTreeBranchItem *b = m_impl->branchItemFactory()->makeBranchItem( this, url, url.prettyURL(), pix ); + b->setChildRecurse( false ); + m_rootBranch = addBranch( b ); + m_rootBranch->setOpen( true ); + connect( m_rootBranch, SIGNAL(populateFinished(KFileTreeViewItem*)), this, SLOT(finishPopulate(KFileTreeViewItem*)) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool FileTreeWidget::shouldBeShown( KFileTreeViewItem* item ) +{ + FileTreeViewItem * i = static_cast<FileTreeViewItem *>( item ); + return ( i->isDir() || ( (m_impl->showNonProjectFiles() || i->isProjectFile() ) + && !matchesHidePattern( i->url().fileName() ) ) ) ; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool FileTreeWidget::matchesHidePattern(const QString &fileName) +{ + QStringList::ConstIterator it; + for (it = m_hidePatterns.begin(); it != m_hidePatterns.end(); ++it) { + QRegExp re(*it, true, true); + if (re.search(fileName) == 0 && (uint)re.matchedLength() == fileName.length()) + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::hideOrShow() +{ + // This is called the first time the tree branch is expanded + FileTreeViewItem* item = static_cast<FileTreeViewItem*>(firstChild()); + if( !item ) + return; + + // Need to skip the root item (which is the sub-directory) + // i.e. "/home/devmario/src/kdevelop/parts/cvsservice" + item = static_cast<FileTreeViewItem*>( item->firstChild() ); + // Now fill the sub-tree + while (item) + { + item->hideOrShow(); + item = static_cast<FileTreeViewItem*>(item->nextSibling()); + } +} + +void FileTreeWidget::finishPopulate(KFileTreeViewItem* item) +{ + if( item == firstChild() ) + { + changeActiveDirectory( "", m_part->project()->activeDirectory() ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::slotItemExecuted( QListViewItem* item ) +{ + if (!item) + return; + + KFileTreeViewItem* ftitem = static_cast<KFileTreeViewItem*>(item); + + if (ftitem->isDir()) + return; + + m_part->partController()->editDocument( ftitem->url() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::slotContextMenu( KListView *, QListViewItem* item, const QPoint &p ) +{ + kdDebug(9017) << "FileTreeWidget::slotContextMenu(...)" << endl; + + KPopupMenu popup( i18n("File Tree"), this ); + + // If an item is selected, fill the file context with selected files' list + if (item) + { + m_impl->fillPopupMenu( &popup, item ); + FileContext context( m_impl->selectedPathUrls() ); + m_part->core()->fillContextMenu( &popup, &context ); + } + + + popup.exec( p ); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString FileTreeWidget::projectDirectory() +{ + return m_part->project()->projectDirectory(); +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Test whether given file (or a directory) is part of this project. + * + * @param fileName or directory to test for presence. + */ +bool FileTreeWidget::isInProject(const QString &fileName) const +{ + return m_projectFiles.contains(fileName); +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Add a bunch of files to this project. + * + * Whenever we load a project or user chooses to add a bunch of files using UI, + * we end in this method. + * We merge the list of files already in the project (if any) with the incoming set. + * + * @param fileList + * @param constructing + * + * @see m_projectFiles + */ +void FileTreeWidget::addProjectFiles( QStringList const & fileList, bool constructing ) +{ + kdDebug(9017) << "files added to project: " << fileList << endl; + + QStringList::ConstIterator it; + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + if( (*it).isEmpty() ) + continue; + kdDebug(9017) << "adding file: " << *it << endl; + const QString file = projectDirectory() + "/" + ( *it ); + if ( !m_projectFiles.contains( file ) ) + { + // We got a new file to add to this project. + // Ensure all the parent directories are part of the project set, too. + QStringList paths = QStringList::split( "/", *it); + paths.pop_back(); + while( !paths.isEmpty() ) + { + // We are adding the directories from longest (the one containing our file), + // to the shortest, measured from root directory of our project. + // Whenever we find out that a directory is already recorded as part of our project, + // we may stop adding, because its parent directories were already added - + // in some previous addition. + QString joinedPaths = paths.join("/"); + if( m_projectFiles.contains( joinedPaths ) ) + break; + m_projectFiles.insert( projectDirectory() + "/" + joinedPaths, true ); + paths.pop_back(); + } + m_projectFiles.insert( file, false ); +// kdDebug(9017) << "file added: " << file << endl; + } + + if ( !constructing ) + { + FileTreeViewItem* item = static_cast<FileTreeViewItem*>(firstChild()); + if( item ) + { + item->setProjectFile( file, true ); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::removeProjectFiles( QStringList const & fileList ) +{ + kdDebug(9017) << "files removed from project: " << fileList.count() << endl; + + QStringList::ConstIterator it; + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + QString file = m_part->project()->projectDirectory() + "/" + ( *it ); + m_projectFiles.remove( file ); + kdDebug(9017) << "file removed: " << file << endl; + + FileTreeViewItem* item = static_cast<FileTreeViewItem*>(firstChild()); + if( item ) + { + item->setProjectFile( file, false ); + } + } +} + +void FileTreeWidget::changeActiveDirectory( const QString& olddir, const QString& newdir ) +{ + FileTreeViewItem* item = static_cast<FileTreeViewItem*>(firstChild()); + if( item ) + { + item->changeActiveDir( projectDirectory() + "/" + olddir, projectDirectory() + "/" + newdir ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::applyHidePatterns( const QString &hidePatterns ) +{ + m_hidePatterns = QStringList::split( ",", hidePatterns ); + hideOrShow(); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString FileTreeWidget::hidePatterns() const +{ + return m_hidePatterns.join( "," ); +} + +/////////////////////////////////////////////////////////////////////////////// + +KDevVersionControl *FileTreeWidget::versionControl() const +{ + if (part() && part()->versionControl()) + return part()->versionControl(); + else + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool FileTreeWidget::showNonProjectFiles() const +{ + return m_impl->showNonProjectFiles(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileTreeWidget::slotImplementationInvalidated() +{ + kdDebug(9017) << "FileTreeWidget::slotImplementationInvalidated()" << endl; + + // Destroy old implementation, create the simpler default impl. and + // reload list view + // remove old branch + removeBranch( m_rootBranch ); + m_rootBranch = 0; // avoid openDirectory() trying to release the branch + + // Restore a clean situation for an eventual new & different implementation + /** \FIXME this for-loop should really go in ~FileTreeViewWidgetImpl() but + * it crashes there: here it works :-/ + */ + for (int i=columns()-1; i>=0; --i) + { + kdDebug(9017) << "Removing column: " << i << endl; + removeColumn( i ); + } + + delete m_impl; + m_impl = new StdFileTreeWidgetImpl( this ); + openDirectory( projectDirectory() ); +} + +#include "filetreewidget.moc" diff --git a/parts/fileview/filetreewidget.h b/parts/fileview/filetreewidget.h new file mode 100644 index 00000000..53dc77d3 --- /dev/null +++ b/parts/fileview/filetreewidget.h @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * Copyright (C) 2003 by Mario Scalas (VCS Support) * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILETREEWIDGET_H_ +#define _FILETREEWIDGET_H_ + +#include <qguardedptr.h> +#include <kfiletreeview.h> + +#include <kdevversioncontrol.h> + +class FileViewPart; +class FileTreeViewWidgetImpl; +class KDevVersionControl; + +/** +* This is FileTree widget for listing files belonging to the project. It does feature: +* - dynamic updates reflecting the state of the project dir and subdirs +* - VCS support for showing VCS fields like state, working and repository revisions +* - bolding the filenames belonging to project to distinguish them from the others +* - dynamic filtering so the user has not to care about temporary files eating screen space ;-) +* +* Design notes +* The class uses two different implementations (referred by m_impl data member): +* - @see VCSFileTreeWidgetImpl for VCS support +* VCS support is detencted by the constructor looking for the @see KDevPlugin::versionControl() member: +* if the current VCS plug-in does offer a @see KDevVCSFileInfoProvider object than this will be used for +* querying about files' data. If neither VCS plugin nor valid info provider is found then the filetreeview +* will fallback to the standard implementation +* - @see StdFileTreeWidgetImpl for standard visualization, just like the KFileTreeView +* +* Each implementation must provide a branch item factory which the file filetree will delegate the creation +* of specific KFileTreeViewItem-derived objects: currently they are both defined in the same .h/.cpp files +* of the implementations listed above. +* +*/ +class FileTreeWidget : public KFileTreeView +{ + Q_OBJECT +public: + FileTreeWidget( FileViewPart *part, QWidget *parent, KDevVCSFileInfoProvider *infoProvider ); + virtual ~FileTreeWidget(); + + void openDirectory(const QString &dirName); + bool shouldBeShown( KFileTreeViewItem* item ); + + QString projectDirectory(); + bool isInProject(const QString &fileName) const; + + FileViewPart *part() const { return m_part; } + + //KDevVCSFileInfoProvider *vcsFileInfoProvider() const; + void applyHidePatterns( const QString &hidePatterns ); + QString hidePatterns() const; + + bool showNonProjectFiles() const; + +public slots: + void hideOrShow(); + + +private slots: + void slotItemExecuted(QListViewItem *item); + void slotContextMenu(KListView *, QListViewItem *item, const QPoint &p); + + void changeActiveDirectory( const QString&, const QString& ); + void finishPopulate(KFileTreeViewItem* item); + + void addProjectFiles( QStringList const & fileList, bool constructing = false ); + void removeProjectFiles( QStringList const & fileList ); + //! We must guard against unloading the used VCS plug-in when using it: we + //! fall back to the implementation (a file view without VCS fields, only filenames) + void slotImplementationInvalidated(); + +private: + bool matchesHidePattern(const QString &fileName); + KDevVersionControl *versionControl() const; + + QStringList m_hidePatterns; + /** + * @brief Set of all the files in this project. + * + * In addition to all the project files, + * we also keep a list of all directories containing any project files - + * effectively holding the whole project tree. + * + * @bug + * Well, it is not just a plain set, + * but rather a map with next-to-useless element value, + * keyed by names of files. + * QT3 does not seem to have a set datatype, + * thus we use the QMap type instead. + */ + QMap<QString, bool> m_projectFiles; + + FileViewPart *m_part; + KFileTreeBranch *m_rootBranch; + QGuardedPtr<FileTreeViewWidgetImpl> m_impl; +}; + +#endif diff --git a/parts/fileview/fileviewpart.cpp b/parts/fileview/fileviewpart.cpp new file mode 100644 index 00000000..d6d6691d --- /dev/null +++ b/parts/fileview/fileviewpart.cpp @@ -0,0 +1,161 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include "fileviewpart.h" + +#include <qwhatsthis.h> +#include <qvbox.h> +#include <qtoolbutton.h> +#include <qdom.h> +#include <kcombobox.h> +#include <qtimer.h> +#include <kaction.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kdevgenericfactory.h> +#include <kdialogbase.h> + +#include "kdevcore.h" +#include "kdevproject.h" +#include "kdevmainwindow.h" + +#include "partwidget.h" +#include "domutil.h" +#include "filetreewidget.h" +#include "vcscolorsconfigwidget.h" +#include "kdevversioncontrol.h" +#include "kdevplugininfo.h" + +#define FILETREE_OPTIONS 1 + +/////////////////////////////////////////////////////////////////////////////// +// static members +/////////////////////////////////////////////////////////////////////////////// + +VCSColors FileViewPart::vcsColors; + +/////////////////////////////////////////////////////////////////////////////// +// class factory +/////////////////////////////////////////////////////////////////////////////// + +typedef KDevGenericFactory<FileViewPart> FileViewFactory; +static const KDevPluginInfo data("kdevfileview"); +K_EXPORT_COMPONENT_FACTORY( libkdevfileview, FileViewFactory( data ) ) + +/////////////////////////////////////////////////////////////////////////////// +// class FileTreeWidget +/////////////////////////////////////////////////////////////////////////////// + +FileViewPart::FileViewPart(QObject *parent, const char *name, const QStringList &) + : KDevPlugin(&data, parent, name ? name : "FileViewPart"), + m_widget( 0 ) +{ + setInstance( FileViewFactory::instance() ); + // setXMLFile("kdevfileview.rc"); + + _configProxy = new ConfigWidgetProxy( core() ); + _configProxy->createProjectConfigPage( i18n("File Tree"), FILETREE_OPTIONS, info()->icon() ); + connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), + this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) ); + + QTimer::singleShot( 1000, this, SLOT(init()) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileViewPart::init( ) +{ + m_widget = new PartWidget( this ); + m_widget->setIcon( SmallIcon( info()->icon() ) ); + mainWindow()->embedSelectView( m_widget, i18n("File Tree"), i18n("File tree view in the project directory") ); + + loadSettings(); + + m_widget->showProjectFiles(); +} + +/////////////////////////////////////////////////////////////////////////////// + +FileViewPart::~FileViewPart() +{ + if (m_widget) + mainWindow()->removeView( m_widget ); + delete m_widget; + + storeSettings(); + + delete _configProxy; +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileViewPart::loadSettings() +{ + const QColor added = QColor( "#CCFF99" ), + updated = QColor( "#FFFFCC" ), + modified = QColor( "#CCCCFF" ), + conflict = QColor( "#FF6666" ), + sticky = QColor( "#FFCCCC" ), + needsPatch = QColor( "#FFCCFF" ), + needsCheckout = QColor( "#FFCCFF" ), + unknown = QColor( white ), + defaultColor = QColor( white ); + + KConfig *cfg = instance()->config(); + + KConfigGroupSaver gs( cfg, "VCS Colors" ); + vcsColors.added = cfg->readColorEntry( "FileAddedColor", &added ); + vcsColors.updated = cfg->readColorEntry( "FileUpdatedColor", &updated ); + vcsColors.sticky = cfg->readColorEntry( "FileStickyColor", &sticky ); + vcsColors.modified = cfg->readColorEntry( "FileModifiedColor", &modified ); + vcsColors.conflict = cfg->readColorEntry( "FileConflictColor", &conflict ); + vcsColors.needsPatch = cfg->readColorEntry( "FileNeedsPatchColor", &needsPatch ); + vcsColors.needsCheckout = cfg->readColorEntry( "FileNeedsCheckoutColor", &needsCheckout ); + vcsColors.unknown = cfg->readColorEntry( "FileUnknownColor", &unknown ); + vcsColors.defaultColor = cfg->readColorEntry( "DefaultColor", &defaultColor ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void FileViewPart::storeSettings() +{ + KConfig *cfg = instance()->config(); + // VCS colors + KConfigGroupSaver gs( cfg, "VCS Colors" ); + cfg->writeEntry( "FileAddedColor", vcsColors.added ); + cfg->writeEntry( "FileUpdatedColor", vcsColors.updated ); + cfg->writeEntry( "FileStickyColor", vcsColors.sticky ); + cfg->writeEntry( "FileModifiedColor", vcsColors.modified ); + cfg->writeEntry( "FileConflictColor", vcsColors.conflict ); + cfg->writeEntry( "FileNeedsPatchColor", vcsColors.needsPatch ); + cfg->writeEntry( "FileNeedsCheckoutColor", vcsColors.needsCheckout ); + cfg->writeEntry( "FileUnknownColor", vcsColors.unknown ); + cfg->writeEntry( "DefaultColor", vcsColors.defaultColor ); +} + +void FileViewPart::insertConfigWidget( const KDialogBase* dlg, QWidget * page, unsigned int pagenumber ) +{ + if ( pagenumber == FILETREE_OPTIONS ) + { + VCSColorsConfigWidget *w = new VCSColorsConfigWidget( this, vcsColors, page, "vcscolorsconfigwidget" ); + connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) ); + } +} + +KDevVersionControl *FileViewPart::versionControl() +{ + return extension<KDevVersionControl>("KDevelop/VersionControl"); +} + +#include "fileviewpart.moc" diff --git a/parts/fileview/fileviewpart.h b/parts/fileview/fileviewpart.h new file mode 100644 index 00000000..9c9a03da --- /dev/null +++ b/parts/fileview/fileviewpart.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILEVIEWPART_H_ +#define _FILEVIEWPART_H_ + +#include <qguardedptr.h> +#include <configwidgetproxy.h> +#include "kdevplugin.h" +#include "vcscolorsconfigwidget.h" + +class PartWidget; +class KDialogBase; +class KDevVersionControl; + +class FileViewPart : public KDevPlugin +{ + Q_OBJECT + +public: + FileViewPart( QObject *parent, const char *name, const QStringList & ); + virtual ~FileViewPart(); + + //! Colors to use for VCS visual feed-back + static VCSColors vcsColors; + + KDevVersionControl *versionControl(); + +private slots: + void insertConfigWidget( const KDialogBase* dlg, QWidget * page, unsigned int ); + void init(); + +private: + void loadSettings(); + void storeSettings(); + + QGuardedPtr<PartWidget> m_widget; + ConfigWidgetProxy * _configProxy; +}; + +#endif diff --git a/parts/fileview/kdevfilegroups.desktop b/parts/fileview/kdevfilegroups.desktop new file mode 100644 index 00000000..41b63d2a --- /dev/null +++ b/parts/fileview/kdevfilegroups.desktop @@ -0,0 +1,86 @@ +[Desktop Entry] +Type=Service +Exec=blubb +Comment=Allows for grouping of project files according to filename patterns. +Comment[ca]=Permet l'agrupació de fitxers del projecte d'acord als patrons dels noms de fitxer. +Comment[da]=Tillader gruppering af projektfiler efter filnavnemønstre. +Comment[de]=Erlaubt die Gruppierung von Projektdateien nach Dateimustern. +Comment[el]=Επιτρέπει την ομαδοποίηση των αρχείων του έργου σύμφωνα με διάφορα μοτίβα. +Comment[es]=Permite la agrupación de archivos del proyecto de acuerdo a patrones en sus nombres. +Comment[et]=Võimaldab rühmitada projekti faile vastavalt failinimede mustritele. +Comment[eu]=Proiektu fitxategiak fitxategi-izen ereduen arabera taldekatzeko aukera ematen du. +Comment[fa]=اجازۀ گروه کردن پروندههای پروژه را طبق الگوهای نام پرونده میدهد. +Comment[fr]=Permet de grouper des fichiers projet en fonction des motifs de noms de fichier. +Comment[gl]=Permite o agrupamento dos arquivos do proxecto seguindo patróns nos seus nomes. +Comment[hi]=फ़ाइल-नाम पैटर्न के आधार पर परियोजना फ़ाइलों का समूह बनाना स्वीकारता है. +Comment[hu]=Lehetővé teszi projektfájlok csoportosítását fájlnévminta alapján +Comment[it]=Permette il raggruppamento dei file di progetto per schemi del nome file. +Comment[ja]=ファイル名のパターンによりプロジェクトファイルのグルーピングを可能にします。 +Comment[ms]=Membenarkan pengumpulan bagi fail projek mengikut corak namafail. +Comment[nds]=Maakt dat Sorteren vun Projektdateien na Dateinaam-Mustern mööglich. +Comment[ne]=फाइल नाम बाँन्की अनुसार परियोजना फाइलहरू समूहबद्ध गर्न अनुमति दिन्छ । +Comment[nl]=Groepeert projectbestanden op grond van patronen in bestandsnamen. +Comment[pl]=Umożliwia grupowanie plików projektu zgodnie z wzorcami nazw plików. +Comment[pt]=Permite o agrupamento de ficheiros de projecto, de acordo com padrões de nomes de ficheiros. +Comment[pt_BR]=Permite agrupar arquivos de projetos de acordo com padrões de nome de arquivo. +Comment[ru]=Позволяет группировать файлы в проекте согласно шаблонам имён. +Comment[sk]=Umožní zoskupenie projektových súborov podľa vzoru mien súborov. +Comment[sr]=Дозвољава груписање пројектних фајлова према облицима имена фајлова. +Comment[sr@Latn]=Dozvoljava grupisanje projektnih fajlova prema oblicima imena fajlova. +Comment[sv]=Tillåter att projektfiler grupperas enligt filnamnsmönster. +Comment[ta]=திட்ட பணிகோப்புகளை கோப்பின் பெயர் அடிப்படையில் அதனை குழுவாக பிரிக்கும். +Comment[tg]=Барои файлҳои дар номҳои қолиб имкон медиҳад. +Comment[tr]=Dosya adı desenlerine göre proje dosyalarının gruplanmasını sağlar. +Comment[zh_CN]=允许你根据文件名模式规类工程文件。 +Comment[zh_TW]=允許專案檔案根據檔名樣式來分群組。 +Name=KDevFileGroups +Name[da]=KDevelop filgrupper +Name[de]=Dateigruppen-Komponente (KDevelop) +Name[hi]=के-डेव-फ़ाइल-ग्रुप्स +Name[nds]=KDevelop-Dateikoppeln +Name[pl]=KDevGrupyPlików +Name[sk]=KDev zoskupenie súborov +Name[sv]=KDevelop filgrupper +Name[ta]=KDev கோப்பு குழுக்கள் +Name[tg]=Гурӯҳҳои файли KDev +Name[zh_TW]=KDevelop 檔案群組 +GenericName=File Groups +GenericName[br]=Strolladoù a restroù +GenericName[ca]=Grups de fitxers +GenericName[da]=Filgrupper +GenericName[de]=Dateigruppen +GenericName[el]=Ομάδες αρχείων +GenericName[es]=Grupos de archivos +GenericName[et]=Failigrupid +GenericName[eu]=Fitxategi taldeak +GenericName[fa]=گروههای پرونده +GenericName[fr]=Groupes de fichiers +GenericName[gl]=Grupos de arquivos +GenericName[hi]=फ़ाइल समूह +GenericName[hu]=Fájlcsoportok +GenericName[it]=Gruppi file +GenericName[ja]=ファイルグループ +GenericName[ms]=Kumpulan Fail +GenericName[nds]=Dateikoppeln +GenericName[ne]=फाइल समूह +GenericName[nl]=Bestandsgroepen +GenericName[pl]=Grupy plików +GenericName[pt]=Grupos de Ficheiros +GenericName[pt_BR]=Grupos de Arquivo +GenericName[ru]=Группы файлов +GenericName[sk]=Zoskupenie súborov +GenericName[sl]=Skupine datotek +GenericName[sr]=Групе фајлова +GenericName[sr@Latn]=Grupe fajlova +GenericName[sv]=Filgrupper +GenericName[ta]=கோப்புக்குழுக்கள் +GenericName[tg]=Гурӯҳи файлҳо +GenericName[tr]=Dosya Grupları +GenericName[zh_CN]=文件分组 +GenericName[zh_TW]=檔案群組 +ServiceTypes=KDevelop/Plugin +Icon=attach +X-KDE-Library=libkdevfilegroups +X-KDevelop-Version=5 +X-KDevelop-Scope=Project +X-KDevelop-Properties=ProjectFileGroupsManagement diff --git a/parts/fileview/kdevfileview.desktop b/parts/fileview/kdevfileview.desktop new file mode 100644 index 00000000..cbdd269c --- /dev/null +++ b/parts/fileview/kdevfileview.desktop @@ -0,0 +1,85 @@ +[Desktop Entry] +Type=Service +Exec=blubb +Comment=Provides a way of navigating and interacting with the source files of the current project. +Comment[ca]=Proporciona un mètode de navegació i interacció amb els fitxers de codi font del projecte actual. +Comment[da]=Sørger for en måde at navigere og interagere med kildefiler for dette projekt. +Comment[de]=Bietet Funktionalität zur Navigation und zum Umgang mit den Quelltexten des aktuellen Projektes. +Comment[el]=Προσφέρει μια μέθοδο πλοήγησης και αλληλεπίδρασης με τα αρχεία πηγαίου κώδικα του τρέχοντος έργου. +Comment[es]=Proporciona un método de navegación e interacción con los archivos de código fuente del proyecto actual. +Comment[et]=Võimaldab aktiivse projekti lähtekoodifailide vahel liikuda ja neis üht-teist ette võtta. +Comment[eu]=Uneko proiektuko itruburu fitxategiekin lan egiteko eta hauen artean nabigatzeko aukera ematen du. +Comment[fa]=راهی برای ناوش و تعامل با پروندههای منبع پروژۀ جاری را فراهم میکند. +Comment[fr]=Fournit un moyen de naviguer et d'interagir avec les fichiers source du projet actuel. +Comment[gl]=Proporciona unha maneira de navegar e interactuar cos ficheiros fonte do proxecto actual. +Comment[hu]=Lehetővé teszi az aktuális projekthez tartozó forrásfájlok áttekintését, kezelését +Comment[it]=Offre un modo per navigare e interagire con il file sorgente del progetto attuale. +Comment[ja]=現在のプロジェクトのソースファイルでナビゲーションおよび対話する方法を提供します。 +Comment[ms]=Menyediakan cara untuk pandu arah dan berinteraksi dengan fail sumber bagi projek semasa. +Comment[nds]=Stellt Ünnerstütten bi't Stüern binnen un för't Hanteren vun de Borndateien vun't aktuelle Projekt praat. +Comment[ne]=हालको परियोजनाको स्रोत फाइलसँग नेभिगेटिङ र अन्तरक्रिया गर्ने तरिका प्रदान गर्दछ । +Comment[nl]=Handig bladeren en zoeken in de broncode-bestanden van het huidige project. +Comment[pl]=Umożliwia metodę nawigacji i interacji z plikami źródłowymi bieżącego projektu. +Comment[pt]=Oferece uma forma de navegar e de interagir com os ficheiros de código do projecto actual. +Comment[pt_BR]=Fornece uma maneira de navegar e interagir com arquivos fonte do projeto atual. +Comment[ru]=Предоставляет способ навигации и взаимодействия с исходными файлами в каталоге текущего проекта. +Comment[sk]=Umožní navigáciu a interakciu so zdrojovými súbormi v aktálnom projekte. +Comment[sr]=Обезбеђује начин навигације и рада са фајловима изворног кôда текућег пројекта. +Comment[sr@Latn]=Obezbeđuje način navigacije i rada sa fajlovima izvornog kôda tekućeg projekta. +Comment[sv]=Erbjuder ett sätt att navigera och arbeta med källkodsfilerna i det aktuella projektet. +Comment[ta]=நடப்பு திட்ட பணியில் உள்ள மூல கோப்பிற்கு வழி செலுத்த மற்றும் உறையாட இது வழி செலுத்தும். +Comment[tg]=Тариқи навигатсияро ва ҳангоми ҳамкорӣ намудан бо файлҳои берунии дар каталоги лоиҳаи ҷорӣ имкон медиҳад. +Comment[tr]=Geçerli projenin kaynak dosyalarında gezinme ve onlarla etkileşime geçme yolu sunar. +Comment[zh_CN]=提供当前工程源文件的浏览和相互关系。 +Comment[zh_TW]=提供目前專案的程式源碼檔的導覽與互動。 +Name=KDevFileView +Name[da]=KDevelop filvisning +Name[de]=Dateibaum (KDevelop) +Name[hi]=के-डेव-फ़ाइल-व्यू +Name[nds]=KDevelop-Dateiboom +Name[pl]=KDevWidokPliku +Name[sk]=KDev pohľad na súbor +Name[sv]=KDevelop filvisning +Name[ta]=KDev கோப்பு காட்சி +Name[tg]=Намоиши файл KDev +Name[zh_TW]=KDevelop 檔案檢視 +GenericName=File Tree +GenericName[br]=Gwezenn restr +GenericName[ca]=Arbre de fitxers +GenericName[da]=Filtræ +GenericName[de]=Dateibaum +GenericName[el]=Δέντρο αρχείων +GenericName[es]=Árbol de archivos +GenericName[et]=Failipuu +GenericName[eu]=Fitxategi zuhaitza +GenericName[fa]=درخت پرونده +GenericName[fr]=Arborescence de fichiers +GenericName[gl]=Árbore de arquivos +GenericName[hi]=फ़ाइल ट्री +GenericName[hu]=Fájl-fa +GenericName[it]=Albero file +GenericName[ja]=ファイルツリー +GenericName[ms]=Pepohon Fail +GenericName[nds]=Dateiboom +GenericName[ne]=फाइल ट्रि +GenericName[nl]=Bestandsboomstructuur +GenericName[pl]=Drzewo plików +GenericName[pt]=Árvore de Ficheiros +GenericName[pt_BR]=Árvore de Arquivo +GenericName[ru]=Дерево файлов +GenericName[sk]=Strom súborov +GenericName[sl]=Datotečno drevo +GenericName[sr]=Дрво фајлова +GenericName[sr@Latn]=Drvo fajlova +GenericName[sv]=Filträd +GenericName[ta]=கோப்பு மரம் +GenericName[tg]=Дарахти файлҳо +GenericName[tr]=Dosya Ağacı +GenericName[zh_CN]=文件树 +GenericName[zh_TW]=檔案樹 +ServiceTypes=KDevelop/Plugin +Icon=folder +X-KDE-Library=libkdevfileview +X-KDevelop-Version=5 +X-KDevelop-Scope=Project +X-KDevelop-Properties=ProjectFileManagement diff --git a/parts/fileview/partwidget.cpp b/parts/fileview/partwidget.cpp new file mode 100644 index 00000000..b3f9baf0 --- /dev/null +++ b/parts/fileview/partwidget.cpp @@ -0,0 +1,144 @@ +/*************************************************************************** + * Copyright (C) 2003 by KDevelop authors * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ +#include "partwidget.h" + +#include <qwhatsthis.h> +#include <qvbox.h> +#include <qlayout.h> +#include <qtoolbutton.h> +#include <qdom.h> +#include <kxmlguiclient.h> +#include <kcombobox.h> +#include <kaction.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "kdevversioncontrol.h" +#include "kdevcore.h" +#include "kdevproject.h" +#include "kdevmainwindow.h" + +#include "fileviewpart.h" +#include "filetreewidget.h" + +/////////////////////////////////////////////////////////////////////////////// +// class PartWidget +/////////////////////////////////////////////////////////////////////////////// + +PartWidget::PartWidget( FileViewPart *part, QWidget *parent ) + : QVBox( parent, "fileviewpartwidget" ), m_filetree( 0 ), + m_filter( 0 ), m_btnFilter( 0 ), m_part( part ) +{ + Q_ASSERT( part && parent ); + + KDevVCSFileInfoProvider *infoProvider = 0; + if (part && part->versionControl() && part->versionControl()->fileInfoProvider()) + infoProvider = part->versionControl()->fileInfoProvider(); + + m_filetree = new FileTreeWidget( m_part, this, infoProvider ); + setCaption(i18n("File Tree")); + m_filetree->setCaption(i18n("File Tree")); + m_filetree->setIcon(SmallIcon("folder")); + QWhatsThis::add(m_filetree, i18n("<b>File tree</b><p>" + "The file viewer shows all files of the project " + "in a tree layout.")); + + QHBox* filterBox = new QHBox( this ); + m_btnFilter = new QToolButton( filterBox ); + m_btnFilter->setIconSet( SmallIconSet("filter" ) ); + m_btnFilter->setToggleButton( true ); + m_filter = new KHistoryCombo( true, filterBox, "filter"); + m_filter->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); + filterBox->setStretchFactor(m_filter, 2); + + connect( m_btnFilter, SIGNAL( clicked() ), this, SLOT( slotBtnFilterClick() ) ); + connect( m_filter, SIGNAL( activated(const QString&) ), this, SLOT( slotFilterChange(const QString&) ) ); + connect( m_filter, SIGNAL( returnPressed(const QString&) ), + m_filter, SLOT( addToHistory(const QString&) ) ); + + QWhatsThis::add + ( m_filter, + i18n("<p>Here you can enter a name filter to limit which files are <b>not displayed</b>." + "<p>To clear the filter, toggle off the filter button to the left." + "<p>To reapply the last filter used, toggle on the filter button." ) ); + QWhatsThis::add + ( m_btnFilter, + i18n("<p>This button clears the name filter when toggled off, or " + "reapplies the last filter used when toggled on.") ); + + m_filter->insertItem( m_filetree->hidePatterns() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +PartWidget::~PartWidget() +{ +} + +/////////////////////////////////////////////////////////////////////////////// + +void PartWidget::showProjectFiles() +{ + m_filetree->openDirectory( m_part->project()->projectDirectory() ); + m_filetree->applyHidePatterns( m_filetree->hidePatterns() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void PartWidget::slotFilterChange( const QString & nf ) +{ + QString f = nf.stripWhiteSpace(); + bool empty = f.isEmpty() || f == "*"; + if ( empty ) + { + m_filter->lineEdit()->setText( QString::null ); + QToolTip::add( m_btnFilter, i18n("Apply last filter (\"%1\")").arg( m_lastFilter ) ); + } + else + { + m_lastFilter = f; + QToolTip::add( m_btnFilter, i18n("Clear filter") ); + } + m_btnFilter->setOn( !empty ); + // this will be never true after the m_filter has been used;) + m_btnFilter->setEnabled( !( empty && m_lastFilter.isEmpty() ) ); + + m_filetree->applyHidePatterns( f ); +} + +/////////////////////////////////////////////////////////////////////////////// +/* + When the button in the filter box toggles: + If off: + If the name filer is anything but "" or "*", reset it. + If on: + Set last filter. +*/ +void PartWidget::slotBtnFilterClick() +{ + if ( !m_btnFilter->isOn() ) + { + slotFilterChange( QString::null ); + } + else + { + m_filter->lineEdit()->setText( m_lastFilter ); + slotFilterChange( m_lastFilter ); + } +} + +void PartWidget::focusInEvent( QFocusEvent * ) +{ + m_filetree->setFocus(); +} + +#include "partwidget.moc" diff --git a/parts/fileview/partwidget.h b/parts/fileview/partwidget.h new file mode 100644 index 00000000..e9d62665 --- /dev/null +++ b/parts/fileview/partwidget.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2003 by KDevelop authors * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _FILEVIEWPARTWIDGET_H_ +#define _FILEVIEWPARTWIDGET_H_ + +#include <qvbox.h> + +class FileViewPart; + +class PartWidget : public QVBox +{ + Q_OBJECT +public: + PartWidget( FileViewPart *part, QWidget *parent = 0 ); + virtual ~PartWidget(); + + class FileTreeWidget *m_filetree; + // Support for filters + class KHistoryCombo *m_filter; + class QToolButton *m_btnFilter; + + void showProjectFiles(); + +protected: + virtual void focusInEvent( QFocusEvent * ); + +private slots: + void slotFilterChange( const QString & nf ); + void slotBtnFilterClick(); + +private: + FileViewPart *m_part; + QString m_lastFilter; +}; + +#endif diff --git a/parts/fileview/stdfiletreewidgetimpl.cpp b/parts/fileview/stdfiletreewidgetimpl.cpp new file mode 100644 index 00000000..b680f2a8 --- /dev/null +++ b/parts/fileview/stdfiletreewidgetimpl.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + + #include <qheader.h> + #include <kdebug.h> + +#include "fileitemfactory.h" +#include "filetreewidget.h" +#include "stdfiletreewidgetimpl.h" + +/////////////////////////////////////////////////////////////////////////////// +// class StdFileTreeViewItem +/////////////////////////////////////////////////////////////////////////////// + +class StdFileTreeViewItem : public filetreeview::FileTreeViewItem +{ +public: + StdFileTreeViewItem( KFileTreeViewItem* parent, KFileItem* item, KFileTreeBranch* branch, bool pf ) + : FileTreeViewItem( parent, item, branch, pf ) {} + StdFileTreeViewItem( KFileTreeView* parent, KFileItem* item, KFileTreeBranch* branch ) + : FileTreeViewItem( parent, item, branch ) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// class StdFileTreeBranchItem +/////////////////////////////////////////////////////////////////////////////// + +class StdFileTreeBranchItem : public filetreeview::FileTreeBranchItem +{ +public: + StdFileTreeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix ) + : FileTreeBranchItem( view, url, name, pix ) {} + virtual ~StdFileTreeBranchItem() {} + virtual KFileTreeViewItem* createTreeViewItem( KFileTreeViewItem* parent, KFileItem* fileItem ); +}; + +/////////////////////////////////////////////////////////////////////////////// + +KFileTreeViewItem* StdFileTreeBranchItem::createTreeViewItem( KFileTreeViewItem* parent, KFileItem* fileItem ) +{ + if (!parent || !fileItem) + return 0; + + FileTreeWidget *lv = static_cast<StdFileTreeViewItem*>( parent )->listView(); + const KURL fileURL = fileItem->url(); + + const bool isDirectory = lv->isInProject( fileURL.path() ); + + return new StdFileTreeViewItem( parent, fileItem, this, isDirectory ); +} + +/////////////////////////////////////////////////////////////////////////////// +// class StdFileItemFactory +/////////////////////////////////////////////////////////////////////////////// + +class StdBranchItemFactory : public filetreeview::BranchItemFactory +{ +public: + virtual filetreeview::FileTreeBranchItem *makeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix ) + { + return new StdFileTreeBranchItem( view, url, name, pix ); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// class StdFileTreeWidgetImpl +/////////////////////////////////////////////////////////////////////////////// + +StdFileTreeWidgetImpl::StdFileTreeWidgetImpl( FileTreeWidget *parent ) + : FileTreeViewWidgetImpl( parent, "stdfiletreewidgetimpl" ) +{ + kdDebug(9017) << "StdFileTreeWidgetImpl::StdFileTreeWidgetImpl()" << endl; + + setBranchItemFactory( new StdBranchItemFactory ); + + parent->addColumn( QString::null ); + header()->hide(); +} + +/////////////////////////////////////////////////////////////////////////////// + +StdFileTreeWidgetImpl::~StdFileTreeWidgetImpl() +{ + kdDebug(9017) << "StdFileTreeWidgetImpl::~StdFileTreeWidgetImpl()" << endl; +} + +#include "stdfiletreewidgetimpl.moc" diff --git a/parts/fileview/stdfiletreewidgetimpl.h b/parts/fileview/stdfiletreewidgetimpl.h new file mode 100644 index 00000000..a9ba7159 --- /dev/null +++ b/parts/fileview/stdfiletreewidgetimpl.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef STDFILETREEWIDGETIMPL_H +#define STDFILETREEWIDGETIMPL_H + +#include "filetreeviewwidgetimpl.h" + +/** +* @author Mario Scalas +* Provides the usual feedback of a KFileTreeView-widget (yeah, it does nothing other +* than providing almost standard KFileTreeViewItems). Adds 1 (one) column to the +* tree view and hides the header. +*/ +class StdFileTreeWidgetImpl : public FileTreeViewWidgetImpl +{ + Q_OBJECT +public: + StdFileTreeWidgetImpl( FileTreeWidget *parent ); + virtual ~StdFileTreeWidgetImpl(); + + /* + * We have no reason not to allow it here + */ + virtual bool canReloadTree() const { return true; } +}; + +#endif diff --git a/parts/fileview/vcscolorsconfigwidget.cpp b/parts/fileview/vcscolorsconfigwidget.cpp new file mode 100644 index 00000000..29de36fe --- /dev/null +++ b/parts/fileview/vcscolorsconfigwidget.cpp @@ -0,0 +1,109 @@ +// +// C++ Implementation: +// +// Description: +// +// +// Author: KDevelop Authors <[email protected]>, (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include <kcolorcombo.h> + +#include "vcscolorsconfigwidget.h" +#include "fileviewpart.h" + +/////////////////////////////////////////////////////////////////////////////// +// struct VCSColors +/////////////////////////////////////////////////////////////////////////////// + +VCSColors::VCSColors() +{ +} + +/////////////////////////////////////////////////////////////////////////////// + +VCSColors::VCSColors( const VCSColors &others ) +{ + *this = others; +} + +/////////////////////////////////////////////////////////////////////////////// + +VCSColors &VCSColors::operator=( const VCSColors &others ) +{ + added = others.added; + conflict = others.conflict; + modified = others.modified; + sticky = others.sticky; + needsPatch = others.needsPatch; + needsCheckout = others.needsCheckout; + unknown = others.unknown; + updated = others.updated; + defaultColor = others.defaultColor; + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +// class VCSColorsConfigWidget +/////////////////////////////////////////////////////////////////////////////// + +VCSColorsConfigWidget::VCSColorsConfigWidget(FileViewPart *part, const VCSColors &vcsColors, + QWidget* parent, const char* name, WFlags fl) + : VCSColorsConfigWidgetBase( parent, name, fl ), m_part( part ) +{ + setColors( vcsColors ); +} + +/////////////////////////////////////////////////////////////////////////////// + +VCSColorsConfigWidget::~VCSColorsConfigWidget() +{ +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSColorsConfigWidget::getColors( VCSColors &vcsColors ) const +{ + vcsColors.added = fileAddedColorCombo->color(); + vcsColors.conflict = fileConflictColorCombo->color(); + vcsColors.modified = fileModifiedColorCombo->color(); + vcsColors.sticky = fileStickyColorCombo->color(); + vcsColors.needsPatch = fileNeedsPatchColorCombo->color(); + vcsColors.needsCheckout = fileNeedsCheckoutColorCombo->color(); + vcsColors.unknown = fileUnknownColorCombo->color(); + vcsColors.updated = fileUpdatedColorCombo->color(); + vcsColors.defaultColor = defaultColorCombo->color(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSColorsConfigWidget::setColors( const VCSColors &vcsColors ) +{ + fileAddedColorCombo->setColor( vcsColors.added ); + fileConflictColorCombo->setColor( vcsColors.conflict ); + fileModifiedColorCombo->setColor( vcsColors.modified ); + fileStickyColorCombo->setColor( vcsColors.sticky ); + fileNeedsPatchColorCombo->setColor( vcsColors.needsPatch ); + fileNeedsCheckoutColorCombo->setColor( vcsColors.needsCheckout ); + fileUnknownColorCombo->setColor( vcsColors.unknown ); + fileUpdatedColorCombo->setColor( vcsColors.updated ); + defaultColorCombo->setColor( vcsColors.defaultColor ); +} + +/*$SPECIALIZATION$*/ + +/////////////////////////////////////////////////////////////////////////////// + +void VCSColorsConfigWidget::slotAccept() +{ + VCSColors selectedColors; + getColors( selectedColors ); + + m_part->vcsColors = selectedColors; +} + +#include "vcscolorsconfigwidget.moc" + diff --git a/parts/fileview/vcscolorsconfigwidget.h b/parts/fileview/vcscolorsconfigwidget.h new file mode 100644 index 00000000..60cd4f52 --- /dev/null +++ b/parts/fileview/vcscolorsconfigwidget.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef VCSCOLORSCONFIGWIDGET_H +#define VCSCOLORSCONFIGWIDGET_H + +#include <qcolor.h> +#include "vcscolorsconfigwidgetbase.h" + +class FileViewPart; + +struct VCSColors +{ + VCSColors(); + VCSColors( const VCSColors &others ); + VCSColors &operator=( const VCSColors &others ); + + QColor modified; + QColor added; + QColor updated; + QColor sticky; + QColor conflict; + QColor needsPatch; + QColor needsCheckout; + QColor unknown; + QColor defaultColor; +}; + +class VCSColorsConfigWidget : public VCSColorsConfigWidgetBase +{ + Q_OBJECT + +public: + VCSColorsConfigWidget( FileViewPart *part, const VCSColors &vcsColors, + QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + virtual ~VCSColorsConfigWidget(); + /*$PUBLIC_FUNCTIONS$*/ + + void getColors( VCSColors &vcsColors ) const; + void setColors( const VCSColors &colors ); + +public slots: + /*$PUBLIC_SLOTS$*/ + // Store settings if the user gives the ok + void slotAccept(); + + +protected: + /*$PROTECTED_FUNCTIONS$*/ + +protected slots: + /*$PROTECTED_SLOTS$*/ + + +private: + FileViewPart *m_part; +}; + +#endif + diff --git a/parts/fileview/vcscolorsconfigwidgetbase.ui b/parts/fileview/vcscolorsconfigwidgetbase.ui new file mode 100644 index 00000000..7e7998ce --- /dev/null +++ b/parts/fileview/vcscolorsconfigwidgetbase.ui @@ -0,0 +1,267 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>VCSColorsConfigWidgetBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>VCSColorsConfigWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>410</width> + <height>324</height> + </rect> + </property> + <property name="caption"> + <string>Colors for VCS Visual Feedback</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Colors to Use for Version Control Feedback</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Updated:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileUpdatedColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Modified:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileModifiedColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Co&nflict:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileConflictColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Added:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileAddedColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Sticky:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileStickyColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>textLabel5_3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Needs checkout:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileStickyColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel5_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Needs patch:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileStickyColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="7" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Un&known:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fileUnknownColorCombo</cstring> + </property> + </widget> + <widget class="QLabel" row="8" column="0"> + <property name="name"> + <cstring>textLabel6_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Default:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>defaultColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="2" column="1"> + <property name="name"> + <cstring>fileModifiedColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="3" column="1"> + <property name="name"> + <cstring>fileConflictColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="7" column="1"> + <property name="name"> + <cstring>fileUnknownColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="6" column="1"> + <property name="name"> + <cstring>fileNeedsCheckoutColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="8" column="1"> + <property name="name"> + <cstring>defaultColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="4" column="1"> + <property name="name"> + <cstring>fileStickyColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="5" column="1"> + <property name="name"> + <cstring>fileNeedsPatchColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="0" column="1"> + <property name="name"> + <cstring>fileAddedColorCombo</cstring> + </property> + </widget> + <widget class="KColorCombo" row="1" column="1"> + <property name="name"> + <cstring>fileUpdatedColorCombo</cstring> + </property> + </widget> + </grid> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kcolorcombo.h</includehint> +</includehints> +</UI> diff --git a/parts/fileview/vcsfiletreewidgetimpl.cpp b/parts/fileview/vcsfiletreewidgetimpl.cpp new file mode 100644 index 00000000..1db873ed --- /dev/null +++ b/parts/fileview/vcsfiletreewidgetimpl.cpp @@ -0,0 +1,353 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#include <qpainter.h> +#include <qheader.h> +#include <qpopupmenu.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include <klocale.h> +#include <kdebug.h> +#include <kdeversion.h> + +//#include <kdevproject.h> +#include <urlutil.h> +#include <domutil.h> + +#include "fileviewpart.h" +#include "filetreewidget.h" +#include "fileitemfactory.h" +#include "vcsfiletreewidgetimpl.h" +#include "vcscolorsconfigwidget.h" + +using namespace filetreeview; + +/////////////////////////////////////////////////////////////////////////////// +// class VCSFileTreeViewItem +/////////////////////////////////////////////////////////////////////////////// + +#define FILENAME_COLUMN 0 +#define STATUS_COLUMN 1 +#define WORKREVISION_COLUMN 2 +#define REPOREVISION_COLUMN 3 + +class VCSFileTreeViewItem : public filetreeview::FileTreeViewItem +{ +public: + VCSFileTreeViewItem( KFileTreeViewItem* parent, KFileItem* item, KFileTreeBranch* branch, bool pf ) + : FileTreeViewItem( parent, item, branch, pf ), m_statusColor( &FileViewPart::vcsColors.unknown ) {} + VCSFileTreeViewItem( KFileTreeView* parent, KFileItem* item, KFileTreeBranch* branch ) + : FileTreeViewItem( parent, item, branch ), m_statusColor( &FileViewPart::vcsColors.unknown ) {} + virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) + { + // paint cell in a different color depending on VCS state + QColorGroup mycg( cg ); + mycg.setColor( QColorGroup::Base, *m_statusColor ); + FileTreeViewItem::paintCell( p, mycg, column, width, alignment ); + } + void setVCSInfo( const VCSFileInfo &info ); + + QString fileName() const { return text( FILENAME_COLUMN ); } + QString workingRev() const { return text( WORKREVISION_COLUMN ); } + QString repositoryRev() const { return text( REPOREVISION_COLUMN ); } + QString status() const { return text( STATUS_COLUMN ); } + void setFileName( const QString &p ) { setText( FILENAME_COLUMN, p ); } + void setWorkingRev( const QString &p ) { setText( WORKREVISION_COLUMN, p ); } + void setRepositoryRev( const QString &p ) { setText( REPOREVISION_COLUMN, p ); } + void setStatus( const VCSFileInfo::FileState status ); + +private: + QColor *m_statusColor; // cached +}; + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeViewItem::setVCSInfo( const VCSFileInfo &info ) +{ + //setFileName( info.fileName ); + setRepositoryRev( info.repoRevision ); + setWorkingRev( info.workRevision ); + setStatus( info.state ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeViewItem::setStatus( const VCSFileInfo::FileState status ) +{ + setText( STATUS_COLUMN, VCSFileInfo::state2String( status ) ); + // Update color too + switch (status) + { + case VCSFileInfo::Added: + m_statusColor = &FileViewPart::vcsColors.added; + break; + case VCSFileInfo::Uptodate: + m_statusColor = &FileViewPart::vcsColors.updated; + break; + case VCSFileInfo::Modified: + m_statusColor = &FileViewPart::vcsColors.modified; + break; + case VCSFileInfo::Conflict: + m_statusColor = &FileViewPart::vcsColors.conflict; + break; + case VCSFileInfo::Sticky: + m_statusColor = &FileViewPart::vcsColors.sticky; + break; + case VCSFileInfo::NeedsCheckout: + m_statusColor = &FileViewPart::vcsColors.needsCheckout; + break; + case VCSFileInfo::NeedsPatch: + m_statusColor = &FileViewPart::vcsColors.needsPatch; + break; + case VCSFileInfo::Unknown: + m_statusColor = &FileViewPart::vcsColors.unknown; + break; + case VCSFileInfo::Directory: + default: + // No color change + m_statusColor = &FileViewPart::vcsColors.defaultColor; + //kdDebug() << "MyFileTreeViewItem::paintCell(): Unknown color!" << endl; + break; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// class VCSFileTreeBranchItem +/////////////////////////////////////////////////////////////////////////////// + +class VCSFileTreeBranchItem : public filetreeview::FileTreeBranchItem +{ +public: + VCSFileTreeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix, + KDevVCSFileInfoProvider *vcsInfoProvider ) + : FileTreeBranchItem( view, url, name, pix ), m_vcsInfoProvider( vcsInfoProvider ) {} +// virtual ~VCSFileTreeBranchItem() {} + virtual KFileTreeViewItem* createTreeViewItem( KFileTreeViewItem* parent, KFileItem* fileItem ); + +private: + KDevVCSFileInfoProvider *m_vcsInfoProvider; +}; + +/////////////////////////////////////////////////////////////////////////////// + +KFileTreeViewItem* VCSFileTreeBranchItem::createTreeViewItem( KFileTreeViewItem* parent, KFileItem* fileItem ) +{ +// kdDebug(9017) << "MyFileTreeBranch::createTreeViewItem(): " + fileItem->url().path() << endl; + if (!parent || !fileItem) + return 0; + + FileTreeWidget *lv = static_cast<filetreeview::FileTreeViewItem*>( parent )->listView(); + const KURL fileURL = fileItem->url(); + const bool isDirectory = lv->isInProject( fileURL.path() ); + + VCSFileTreeViewItem *newItem = new VCSFileTreeViewItem( parent, fileItem, this, isDirectory ); + +// QString fileName = fileURL.fileName(); +// QString dirName = URLUtil::extractPathNameRelative( lv->projectDirectory(), fileURL.directory() ); + +// const VCSFileInfoMap &vcsFiles = *m_vcsInfoProvider->status( dirName ); +// kdDebug(9017) << "Dir has " << vcsFiles.count() << " registered files!" << endl; +// if (vcsFiles.contains( fileName )) +// newItem->setVCSInfo( vcsFiles[ fileName ] ); +// else +// kdDebug(9017) << "!!!No VCS info for this file!!!" << endl; + return newItem; +} + +/////////////////////////////////////////////////////////////////////////////// +// class VCSFileItemFactory +/////////////////////////////////////////////////////////////////////////////// + +class VCSBranchItemFactory : public filetreeview::BranchItemFactory +{ +public: + VCSBranchItemFactory( KDevVCSFileInfoProvider *vcsInfoProvider ) : m_vcsInfoProvider( vcsInfoProvider ) {} + virtual filetreeview::FileTreeBranchItem *makeBranchItem( KFileTreeView* view, const KURL& url, const QString& name, const QPixmap& pix ) + { + return new VCSFileTreeBranchItem( view, url, name, pix, m_vcsInfoProvider ); + } +private: + KDevVCSFileInfoProvider *m_vcsInfoProvider; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class VCSFileTreeWidgetImpl +/////////////////////////////////////////////////////////////////////////////// + +VCSFileTreeWidgetImpl::VCSFileTreeWidgetImpl( FileTreeWidget *parent, KDevVCSFileInfoProvider *infoProvider ) + : FileTreeViewWidgetImpl( parent, "vcsfiletreewidgetimpl" ), + m_actionToggleShowVCSFields( 0 ), m_actionSyncWithRepository( 0 ), m_vcsInfoProvider( infoProvider ), + m_isSyncingWithRepository( false ), m_vcsStatusRequestedItem( 0 ) +{ + kdDebug(9017) << "VCSFileTreeWidgetImpl::VCSFileTreeWidgetImpl()" << endl; + + Q_ASSERT( m_vcsInfoProvider ); + setBranchItemFactory( new VCSBranchItemFactory( m_vcsInfoProvider ) ); + + // Update the #define order on top if you change this order! + parent->addColumn( "Filename" ); + parent->addColumn( "Status" ); + parent->addColumn( "Work" ); + parent->addColumn( "Repo" ); + + connect( m_vcsInfoProvider, SIGNAL(statusReady(const VCSFileInfoMap&, void *)), + this, SLOT(vcsDirStatusReady(const VCSFileInfoMap&, void*)) ); + // Harakiri itself if the infoProvider object is destroyed since we cannot work anymore :-( + connect( m_vcsInfoProvider, SIGNAL(destroyed()), SIGNAL(implementationInvalidated()) ); + + m_actionToggleShowVCSFields = new KToggleAction( i18n("Show VCS Fields"), KShortcut(), + this, "actiontoggleshowvcsfieldstoggleaction" ); + m_actionToggleShowVCSFields->setCheckedState(i18n("Hide VCS Fields")); + QString aboutAction = i18n("<b>Show VCS fields</b><p>Shows <b>Revision</b> and <b>Timestamp</b> for each file contained in VCS repository."); + m_actionToggleShowVCSFields->setWhatsThis( aboutAction ); + connect( m_actionToggleShowVCSFields, SIGNAL(toggled(bool)), this, SLOT(slotToggleShowVCSFields(bool)) ); + + m_actionSyncWithRepository = new KAction( i18n( "Sync with Repository"), KShortcut(), + this, SLOT(slotSyncWithRepository()), this, "actionsyncwithrepository" ); + aboutAction = i18n("<b>Sync with repository</b><p>Synchronize file status with remote repository."); + m_actionSyncWithRepository->setWhatsThis( aboutAction ); + + QDomDocument &dom = projectDom(); + m_actionToggleShowVCSFields->setChecked( DomUtil::readBoolEntry(dom, "/kdevfileview/tree/showvcsfields") ); + slotToggleShowVCSFields( showVCSFields() ); // show or hide fields depending on read settings + connect( parent, SIGNAL(expanded(QListViewItem*)), this, SLOT(slotDirectoryExpanded(QListViewItem*))); +} + +/////////////////////////////////////////////////////////////////////////////// + +VCSFileTreeWidgetImpl::~VCSFileTreeWidgetImpl() +{ + kdDebug(9017) << "VCSFileTreeWidgetImpl::~VCSFileTreeWidgetImpl()" << endl; + + QDomDocument &dom = projectDom(); + DomUtil::writeBoolEntry( dom, "/kdevfileview/tree/showvcsfields", showVCSFields() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool VCSFileTreeWidgetImpl::canReloadTree() const +{ + return !m_isSyncingWithRepository; +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeWidgetImpl::fillPopupMenu( QPopupMenu *popupMenu, QListViewItem *item ) const +{ + FileTreeViewWidgetImpl::fillPopupMenu( popupMenu, item ); + + // Submenu for visualization options + m_actionToggleShowVCSFields->plug( popupMenu ); + // Give a change for syncing status with remote repository: a file info provider must + // be available and the item must be a project directory + FileTreeViewItem *fileItem = static_cast<FileTreeViewItem *>( item ); + if (fileItem->isDir()) + { + m_vcsStatusRequestedItem = fileItem; + popupMenu->insertSeparator(); + m_actionSyncWithRepository->plug( popupMenu ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeWidgetImpl::slotToggleShowVCSFields( bool checked ) +{ + kdDebug(9017) << "VCSFileTreeWidgetImpl::slotToggleShowVCSFields()" << endl; + + if (checked) + { + setColumnWidth( 0, contentsWidth() / 2 ); // "Filename" + setColumnWidth( 1, contentsWidth() / 4 ); // "status" + setColumnWidth( 2, contentsWidth() / 5 ); // "work revision" + setColumnWidth( 3, contentsWidth() / 5 ); // "repository revision" + header()->show(); + } + else + { + setColumnWidth( 3 ,0 ); // Hide columns + setColumnWidth( 2 ,0 ); + setColumnWidth( 1, 0 ); + setColumnWidth( 0, contentsWidth() ); // Make the "Filename" column to occupy all the row + header()->hide(); + } + + triggerUpdate(); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool VCSFileTreeWidgetImpl::showVCSFields() const +{ + return m_actionToggleShowVCSFields->isChecked(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeWidgetImpl::vcsDirStatusReady( const VCSFileInfoMap &modifiedFiles, void *callerData ) +{ + kdDebug(9017) << "VCSFileTreeWidgetImpl::vcsDirStatusReady(const VCSFileInfoMap &, void*)" << endl; + + VCSFileTreeViewItem *item = static_cast<VCSFileTreeViewItem*>( callerData ); +// Q_ASSERT( item ); // this must _not_ fail! + if( !item ){ + kdDebug(9017) << "static_cast<VCSFileTreeViewItem*>( callerData ) failed" << endl; + return; + } + // Update vcs file info for all childs in this tree folder ... + item = static_cast<VCSFileTreeViewItem*>( item->firstChild() ); + while (item) + { + const QString fileName = item->fileName(); + kdDebug(9017) << "Widget item filename is: " << fileName << endl; + if (modifiedFiles.contains( fileName )) + { + const VCSFileInfo &vcsInfo = modifiedFiles[ fileName ]; + kdDebug(9017) << "Nice! Found info for this file: " << vcsInfo.toString() << endl; + item->setVCSInfo( modifiedFiles[ fileName ] ); + } + else + kdDebug(9017) << "Map does not contain anything useful about this file ;-( " << fileName << endl; + item = static_cast<VCSFileTreeViewItem*>( item->nextSibling() ); + } + triggerUpdate(); + + m_isSyncingWithRepository = false; +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeWidgetImpl::slotSyncWithRepository() +{ + kdDebug(9017) << "VCSFileTreeWidgetImpl::slotSyncWithRepository()" << endl; + const VCSFileTreeViewItem *myFileItem = static_cast<VCSFileTreeViewItem *>( m_vcsStatusRequestedItem ); + const QString relDirPath = URLUtil::extractPathNameRelative( projectDirectory(), myFileItem->fileItem()->url().path() ); + kdDebug(9017) << "VCS Info requested for: " << relDirPath << endl; + m_vcsInfoProvider->requestStatus( relDirPath, m_vcsStatusRequestedItem ); + m_isSyncingWithRepository = true; +} + +/////////////////////////////////////////////////////////////////////////////// + +void VCSFileTreeWidgetImpl::slotDirectoryExpanded( QListViewItem* aItem ) +{ + VCSFileTreeViewItem *item = static_cast<VCSFileTreeViewItem *>( aItem ); + if( !item ) return; + + const QString relDirPath = URLUtil::extractPathNameRelative( projectDirectory(), item->fileItem()->url().path() ); + kdDebug(9017) << "ASync VCS Info requested for: " << relDirPath << endl; + m_vcsInfoProvider->requestStatus( relDirPath, item, false, false ); + +// m_isSyncingWithRepository = true; + +} + +#include "vcsfiletreewidgetimpl.moc" diff --git a/parts/fileview/vcsfiletreewidgetimpl.h b/parts/fileview/vcsfiletreewidgetimpl.h new file mode 100644 index 00000000..de4dc8c1 --- /dev/null +++ b/parts/fileview/vcsfiletreewidgetimpl.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2003 by Mario Scalas * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef VCSFILETREEWIDGETIMPL_H +#define VCSFILETREEWIDGETIMPL_H + +#include "filetreeviewwidgetimpl.h" + +class KDevVCSFileInfoProvider; +class KAction; +class KToggleAction; + +/** +* @author Mario Scalas +* Provides VCS feedback to the standard features. +*/ +class VCSFileTreeWidgetImpl : public FileTreeViewWidgetImpl +{ + Q_OBJECT +public: + VCSFileTreeWidgetImpl( FileTreeWidget *parent, KDevVCSFileInfoProvider *infoProvider ); + virtual ~VCSFileTreeWidgetImpl(); + + /* + * We must avoid a reload operation while we syncing with the repository since this + * will break our job. + */ + virtual bool canReloadTree() const; + /* + * Add "sync with repository" and "show VCS fields" options to the context menu. + */ + virtual void fillPopupMenu( QPopupMenu *popupMenu, QListViewItem *item ) const; + +private slots: + //! show/hide the header and the additional fields (status and versions) + void slotToggleShowVCSFields( bool checked ); + //! start a sync operation with the remote repository: this may take a while so we use + //! the async interface provided by the KDevVCSFileInfoProvider interface + void slotSyncWithRepository(); + //! when the requested info are ready the infoProvider object will be so kind the + //! to give them to us in a ready-to-use format: we'll use that info to update all + //! the items which are childs of the @see filetreeview::FileTreeViewItem stored in + //! @p callerData. + void vcsDirStatusReady( const VCSFileInfoMap &modifiedFiles, void *callerData ); + void slotDirectoryExpanded( QListViewItem* ); + +private: + bool showVCSFields() const; + + KToggleAction *m_actionToggleShowVCSFields; + KAction *m_actionSyncWithRepository; + KDevVCSFileInfoProvider *m_vcsInfoProvider; + //! We use this guard to avoid enabling the "reload tree" action when performing + //! syncing with remote repositories. + bool m_isSyncingWithRepository; + mutable KFileTreeViewItem *m_vcsStatusRequestedItem; +}; + +#endif |