diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-15 17:32:48 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-15 17:32:48 +0000 |
commit | e2f541c98dfa4081fa3ab3d28f08ea2309281884 (patch) | |
tree | cb721a55bc88753ddeb9754dc98ef45e2850ce30 /src | |
download | tdesvn-e2f541c98dfa4081fa3ab3d28f08ea2309281884.tar.gz tdesvn-e2f541c98dfa4081fa3ab3d28f08ea2309281884.zip |
Added KDE3 version of kdesvn
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kdesvn@1103685 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
504 files changed, 52128 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..a35f2fe --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,57 @@ +ADD_EXECUTABLE(kdesvnaskpass askpass/kdesvn-askpass.cpp) +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/kde3) + +SET(kdesvnsrc + main.cpp + kdesvn.cpp + urldlg.cpp + commandline.cpp) + +SET(partsrc + kdesvn_events.cpp + kdesvn_events.h + kdesvn_part.cpp + kdesvnview.cpp + commandline_part.cpp) + +KDE3_AUTOMOC(${kdesvnsrc}) +KDE3_AUTOMOC(${partsrc}) + +SET(partsrc ${partsrc} kdesvn_part.h kdesvnview.h commandline_part.h) +SET(kdesvnsrc ${kdesvnsrc} kdesvn.h urldlg.h commandline.h) + +ADD_SUBDIRECTORY(svnqt) +ADD_SUBDIRECTORY(ksvnwidgets) +ADD_SUBDIRECTORY(settings) +ADD_SUBDIRECTORY(svnfrontend) +ADD_SUBDIRECTORY(helpers) +ADD_SUBDIRECTORY(kdesvnd) +ADD_SUBDIRECTORY(kiosvn) +ADD_SUBDIRECTORY(pics) +ADD_SUBDIRECTORY(icons) + +ADD_EXECUTABLE(kdesvn ${kdesvnsrc}) + +KDE3_ADD_KPART(kdesvnpart WITH_PREFIX ${partsrc}) +TARGET_LINK_LIBRARIES(kdesvnpart svnfrontend kdesvnhelpers ksvnwidgets settingsdlgs kdesvncfgreader svnqt + ${QT_AND_KDECORE_LIBS} ${KDE3_KIO_LIBRARY} ${KDE3_PART_LIBRARY} ${KDE3_UI_LIBRARY} ${KDE3_WALLET_LIBRARY} ) +SET_TARGET_PROPERTIES(kdesvnpart + PROPERTIES + LINK_FLAGS "${_BASE_LDADD} ${APR_EXTRA_LIBFLAGS} ${APU_EXTRA_LIBFLAGS} ${LINK_NO_UNDEFINED}") + +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/src/svnqt) + +KDESVN_GENERATE_LIBTOOL_FILE(kdesvnpart) + + +TARGET_LINK_LIBRARIES(kdesvnaskpass ${QT_AND_KDECORE_LIBS} ${KDE3_UI_LIBRARY}) +TARGET_LINK_LIBRARIES(kdesvn ${QT_AND_KDECORE_LIBS} ${KDE3_UI_LIBRARY} ${KDE3_PART_LIBRARY} ${KDE3_DCOP_LIBRARY} ${KDE3_KIO_LIBRARY}) + +INSTALL(TARGETS kdesvn kdesvnaskpass kdesvnpart + RUNTIME DESTINATION ${BIN_INSTALL_DIR} + LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR}) + +# the resources +INSTALL(FILES kdesvnui.rc DESTINATION ${DATA_INSTALL_DIR}/kdesvn) +INSTALL(FILES kdesvn_part.rc DESTINATION ${DATA_INSTALL_DIR}/kdesvnpart) +INSTALL(FILES kdesvn.desktop DESTINATION ${XDG_APPS_DIR}) diff --git a/src/README b/src/README new file mode 100644 index 0000000..f04a563 --- /dev/null +++ b/src/README @@ -0,0 +1,81 @@ +----------------------------------------------- +Kde application framework template quickstart +Author: Thomas Nagy +Date: 2004-03-22 +----------------------------------------------- + +This README file explains you basic things for starting with +this application template. + + +** Building and installing ** + +* Build the configure script by "make -f Makefile.cvs" + +* To clean, use "make clean", and to clean everything +(remove the makefiles, etc), use "make distclean" + +* To distribute your program, try "make dist". +This will make a compact tarball archive of your release with the +necessary scripts inside. + +* Modifying the auto-tools scripts +for automake scripts there is an excellent tutorial there : +http://developer.kde.org/documentation/other/makefile_am_howto.html + +* Simplify your life : install the project in your home directory for +testing purposes. +./configure --prefix=/home/user/dummyfolder/ +In the end when you finished the development you can +rm -rf /home/user/dummyfolder/ +without fear. + + +** Technologies ** + +* Build the menus of your application easily +kde applications now use an xml file (*ui.rc file) to build the menus. +This allow a great customization of the application. However, when +programming the menu is shown only after a "make install" + +For more details, consult : +http://devel-home.kde.org/~larrosa/tutorial/p9.html +http://developer.kde.org/documentation/tutorials/xmlui/preface.html + +* Use KConfig XT to create your configuration dialogs and make +them more maintainable. + +For more details, consult : +http://developer.kde.org/documentation/tutorials/kconfigxt/kconfigxt.html + +* With KParts, you can embed other kde components in your program, or make your program +embeddable in other apps. For example, the kmplayer kpart can be called to play videos +in your app. + +For more details, consult : +http://www-106.ibm.com/developerworks/library/l-kparts/ +http://developer.kde.org/documentation/tutorials/dot/writing-plugins.html +http://developer.kde.org/documentation/tutorials/developing-a-plugin-structure/index.html + +* With dcop, you can control your app from other applications +Make sure to include K_DCOP and a kdcop: section in your .h file +http://developer.kde.org/documentation/tutorials/dot/dcopiface/dcop-interface.html + + +** Documentation ** + +* For the translations : +1. Download a patched gettext which can be found at: + http://public.kde.planetmirror.com/pub/kde/devel/gettext-kde/ +2. Install that gettext in ~/bin/ +3. cd ~/yourproject, export PATH=~/bin:$PATH, export +KDEDIR=/where_your_KDE3_is +4. make -f admin/Makefile.common package-messages +5. make package-messages +6. Translate the po files (not the pot!!) with kbabel or xemacs + +* Do not forget to write the documentation for your kde app +edit the documentation template index.docbook in doc/ + + + diff --git a/src/askpass/kdesvn-askpass.cpp b/src/askpass/kdesvn-askpass.cpp new file mode 100644 index 0000000..2f6ed4c --- /dev/null +++ b/src/askpass/kdesvn-askpass.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include <qregexp.h> +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <kpassdlg.h> + +#include <iostream> +static KCmdLineOptions options[] = +{ + { "+[prompt]", I18N_NOOP("prompt"), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char** argv) +{ + KAboutData about("kdesvnaskpass",I18N_NOOP("kdesvnaskpass"),"0.1", + I18N_NOOP("ssh-askpass for kdesvn"), + KAboutData::License_LGPL, + I18N_NOOP("Copyright (c) 2005 Rajko Albrecht")); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + // no need to register with the dcop server + KApplication::disableAutoDcopRegistration(); + + KApplication app; + // no need for session management + app.disableSessionManagement(); + QString prompt; + + if( !KCmdLineArgs::parsedArgs()->count() ) { + prompt = i18n("Please enter your password below."); + } else { + prompt = KCmdLineArgs::parsedArgs()->arg(0); + } + QCString pw; + KPasswordDialog::disableCoreDumps(); + if (KPasswordDialog::getPassword(pw,prompt,0)==KPasswordDialog::Accepted) { + std::cout << pw << std::endl; + /* cleanup memory */ + pw.replace(0,pw.length(),"0"); + return 0; + } + return 1; +} diff --git a/src/commandline.cpp b/src/commandline.cpp new file mode 100644 index 0000000..4aaabd3 --- /dev/null +++ b/src/commandline.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "commandline.h" +#include "kdesvn_part.h" +#include "commandline_part.h" +#include <kcmdlineargs.h> +#include <kdialogbase.h> +#include <ktextbrowser.h> +#include <kapplication.h> +#include <klocale.h> +#include <qstring.h> +#include <qlayout.h> +#include <qvbox.h> + +class CommandLineData +{ +public: + CommandLineData():cmd(""){}; + virtual ~CommandLineData(){}; + + void displayHelp(); + + QString cmd; +}; + +CommandLine::CommandLine(KCmdLineArgs*_args) +{ + m_args = _args; + m_data = new CommandLineData; +} + +CommandLine::~CommandLine() +{ +} + +int CommandLine::exec() +{ + if (!m_args||m_args->count()<1) { + return -1; + } + if (m_args->count()<2) { + m_data->cmd = "help"; + } else { + m_data->cmd = m_args->arg(1); + } + if (m_data->cmd=="help") { + m_data->displayHelp(); + return 0; + } + KLibFactory *factory = KLibLoader::self()->factory("libkdesvnpart"); + if (factory) { + if (QCString(factory->className())!="cFactory") { + kdDebug()<<"wrong factory"<<endl; + return -1; + } + cFactory*cfa = static_cast<cFactory*>(factory); + commandline_part * cpart = cfa->createCommandIf((QObject*)0,(const char*)0,m_args); + int res = cpart->exec(); + return res; + } + return 0; +} + +void CommandLineData::displayHelp() +{ + kapp->invokeHelp("kdesvn-commandline","kdesvn"); +} diff --git a/src/commandline.h b/src/commandline.h new file mode 100644 index 0000000..5edec07 --- /dev/null +++ b/src/commandline.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef COMMANDLINE_H +#define COMMANDLINE_H + +class KCmdLineArgs; +class CommandLineData; + +/** +@author Rajko Albrecht +*/ +class CommandLine{ +public: + CommandLine(KCmdLineArgs*); + virtual ~CommandLine(); + + virtual int exec(); + +protected: + KCmdLineArgs*m_args; + CommandLineData*m_data; +}; + +#endif diff --git a/src/commandline_part.cpp b/src/commandline_part.cpp new file mode 100644 index 0000000..ea06722 --- /dev/null +++ b/src/commandline_part.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "commandline_part.h" +#include "kdesvn_part.h" +#include "svnfrontend/commandexec.h" + +#include <kstandarddirs.h> + +commandline_part::commandline_part(QObject *parent, const char *name,KCmdLineArgs *args) + : QObject(parent, name) +{ + KGlobal::locale()->insertCatalogue("kdesvn"); + KInstance * inst = kdesvnPartFactory::instance(); + KGlobal::locale()->insertCatalogue(inst->instanceName()); + KGlobal::dirs()->addResourceType( inst->instanceName() + "data", + KStandardDirs::kde_default("data")+ QString::fromLatin1( inst->instanceName() ) + '/' ); + + + m_pCPart = new CommandExec(this,name?QString(name)+QString("_exec"):QString::fromLatin1("command_executer"),args); +} + +commandline_part::~commandline_part() +{ +} + +int commandline_part::exec() +{ + return m_pCPart->exec(); +} + +#include "commandline_part.moc" diff --git a/src/commandline_part.h b/src/commandline_part.h new file mode 100644 index 0000000..03a8366 --- /dev/null +++ b/src/commandline_part.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef COMMANDLINE_PART_H +#define COMMANDLINE_PART_H + +#include <qobject.h> + +class CommandExec; +class KCmdLineArgs; + +/** +@author Rajko Albrecht +*/ +class commandline_part : public QObject +{ + Q_OBJECT +public: + commandline_part(QObject *parent, const char *name, KCmdLineArgs *args); + virtual ~commandline_part(); + virtual int exec(); +private: + CommandExec*m_pCPart; + +}; + +#endif diff --git a/src/eventnumbers.h b/src/eventnumbers.h new file mode 100644 index 0000000..50c9038 --- /dev/null +++ b/src/eventnumbers.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2005 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _EVENT_NUMBERS_H +#define _EVENT_NUMBERS_H + +#include <qevent.h> + +#define EVENT_THREAD_FINISHED QEvent::User +#define EVENT_THREAD_SSL_TRUST_PROMPT QEvent::User+1 +#define EVENT_THREAD_LOGIN_PROMPT QEvent::User+2 +#define EVENT_THREAD_LOGMSG_PROMPT QEvent::User+3 +#define EVENT_THREAD_CERT_PW_PROMPT QEvent::User+4 +#define EVENT_THREAD_CERT_SELECT_PROMPT QEvent::User+5 +#define EVENT_THREAD_NOTIFY QEvent::User+6 +#define EVENT_LOGCACHE_FINISHED QEvent::User+7 +#define EVENT_LOGCACHE_STATUS QEvent::User+8 +#define EVENT_THREAD_LOGIN_SAVED QEvent::User+9 + +#endif diff --git a/src/helpers/CMakeLists.txt b/src/helpers/CMakeLists.txt new file mode 100644 index 0000000..c9b0051 --- /dev/null +++ b/src/helpers/CMakeLists.txt @@ -0,0 +1,14 @@ +SET(helperssrc + ktranslateurl.cpp + sshagent.cpp + sub2qt.cpp) + +FILE(GLOB hdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") + +KDE3_AUTOMOC(${helperssrc} ) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) +ADD_LIBRARY(kdesvnhelpers STATIC ${helperssrc} ${hdr}) + +SET_TARGET_PROPERTIES(kdesvnhelpers + PROPERTIES + COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) diff --git a/src/helpers/ktranslateurl.cpp b/src/helpers/ktranslateurl.cpp new file mode 100644 index 0000000..8c5e903 --- /dev/null +++ b/src/helpers/ktranslateurl.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "ktranslateurl.h" + +#include <kglobal.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kfileitem.h> +#include <kdesktopfile.h> + +#include <qstringlist.h> +#include <qdir.h> + +namespace helpers { + +KTranslateUrl::KTranslateUrl() +{ +} + + +KTranslateUrl::~KTranslateUrl() +{ +} + +KURL KTranslateUrl::translateSystemUrl(const KURL&_url) +{ + QString proto = _url.protocol(); + KURL res; + QString name,path; + + if (proto!="system") { + return _url; + } + KGlobal::dirs()->addResourceType("system_entries", + KStandardDirs::kde_default("data") + "systemview"); + QStringList dirList = KGlobal::dirs()->resourceDirs("system_entries"); + if (!parseURL(_url,name,path)) { + return _url; + } + res = findSystemBase(name); + if (!res.isValid()) { + return _url; + } + res.addPath(path); + res.setQuery(_url.query()); + return res; +} + +bool KTranslateUrl::parseURL(const KURL&url,QString&name,QString&path) +{ + QString url_path = url.path(); + int i = url_path.find('/', 1); + if (i > 0) + { + name = url_path.mid(1, i-1); + path = url_path.mid(i+1); + } + else + { + name = url_path.mid(1); + path = QString::null; + } + + return name != QString::null; +} + +KURL KTranslateUrl::findSystemBase(const QString&filename) +{ + QStringList dirList = KGlobal::dirs()->resourceDirs("system_entries"); + + QStringList::ConstIterator dirpath = dirList.begin(); + QStringList::ConstIterator end = dirList.end(); + for(; dirpath!=end; ++dirpath) + { + QDir dir = *dirpath; + if (!dir.exists()) continue; + + QStringList filenames + = dir.entryList( QDir::Files | QDir::Readable ); + + + KIO::UDSEntry entry; + + QStringList::ConstIterator name = filenames.begin(); + QStringList::ConstIterator endf = filenames.end(); + + for(; name!=endf; ++name) + { + if (*name==filename+".desktop") + { + KDesktopFile desktop(*dirpath+filename+".desktop", true); + if ( desktop.readURL().isEmpty() ) + { + KURL url; + url.setPath( desktop.readPath() ); + return url; + } + + return desktop.readURL(); + } + } + } + + return KURL(); +} + +} + + +/*! + \fn helpers::KTranslateUrl::makeKdeUrl(const QString&inUrl) + */ +QString helpers::KTranslateUrl::makeKdeUrl(const QString&_proto) +{ + QString proto; + if (_proto.startsWith("svn+")){ + proto = "k"+_proto; + } else if (_proto== QString("svn")){ + proto = "ksvn"; + } else { + proto = "ksvn+"+_proto; + } + return proto; +} diff --git a/src/helpers/ktranslateurl.h b/src/helpers/ktranslateurl.h new file mode 100644 index 0000000..bad6a6a --- /dev/null +++ b/src/helpers/ktranslateurl.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef HELPERSKTRANSLATEURL_H +#define HELPERSKTRANSLATEURL_H + +#include <kurl.h> + +namespace helpers { + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class KTranslateUrl{ +public: + KTranslateUrl(); + ~KTranslateUrl(); + + static KURL translateSystemUrl(const KURL&); + static bool parseURL(const KURL&,QString&name,QString&path); + static KURL findSystemBase(const QString&name); + static QString makeKdeUrl(const QString&inUrl); +}; + +} + +#endif diff --git a/src/helpers/sshagent.cpp b/src/helpers/sshagent.cpp new file mode 100644 index 0000000..ccde212 --- /dev/null +++ b/src/helpers/sshagent.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "sshagent.h" +#include "kdesvn-config.h" + +#include <qregexp.h> +#include <kapplication.h> +#include <kdeversion.h> +#include <kprocess.h> +#include <kdebug.h> + +#include <stdlib.h> + + +// initialize static member variables +bool SshAgent::m_isRunning = false; +bool SshAgent::m_isOurAgent = false; +bool SshAgent::m_addIdentitiesDone = false; +QString SshAgent::m_authSock = QString::null; +QString SshAgent::m_pid = QString::null; + + +SshAgent::SshAgent(QObject* parent, const char* name) + : QObject(parent, name) +{ +} + + +SshAgent::~SshAgent() +{ +} + + +bool SshAgent::querySshAgent() +{ + if( m_isRunning ) + return true; + + // Did the user already start a ssh-agent process? + char* pid; + if( (pid = ::getenv("SSH_AGENT_PID")) != 0 ) + { + m_pid = QString::fromLocal8Bit(pid); + + char* sock = ::getenv("SSH_AUTH_SOCK"); + if( sock ) + m_authSock = QString::fromLocal8Bit(sock); + /* make sure that we have a askpass program. + * on some systems something like that isn't installed.*/ +#ifdef FORCE_ASKPASS + kdDebug()<<"Using test askpass"<<endl; +#ifdef HAS_SETENV + ::setenv("SSH_ASKPASS",FORCE_ASKPASS,1); +#else + ::putenv("SSH_ASKPASS="FORCE_ASKPASS); +#endif +#else +/* + char*agent = ::getenv("SSH_ASKPASS"); + if (!agent) { +*/ +#ifdef HAS_SETENV + ::setenv("SSH_ASKPASS", "kdesvnaskpass",1); +#else + ::putenv("SSH_ASKPASS=kdesvnaskpass"); +#endif +/* + } +*/ +#endif + m_isOurAgent = false; + m_isRunning = true; + } + // We have to start a new ssh-agent process + else + { + m_isOurAgent = true; + m_isRunning = startSshAgent(); + } + + return m_isRunning; +} + + +bool SshAgent::addSshIdentities(bool force) +{ + if (m_addIdentitiesDone && !force) { + return true; + } + + + if( !m_isRunning || (!m_isOurAgent&&!force)) { + return false; + } + + // add identities to ssh-agent + KProcess proc; + + proc.setEnvironment("SSH_AGENT_PID", m_pid); + proc.setEnvironment("SSH_AUTH_SOCK", m_authSock); + +#ifdef FORCE_ASKPASS + kdDebug()<<"Using test askpass"<<endl; + proc.setEnvironment("SSH_ASKPASS",FORCE_ASKPASS); +#else + char*agent = 0; +/* + if (force) { + agent = ::getenv("SSH_ASKPASS"); + } +*/ + if (!agent) { + proc.setEnvironment("SSH_ASKPASS", "kdesvnaskpass"); + } +#endif + + proc << "ssh-add"; + + connect(&proc, SIGNAL(receivedStdout(KProcess*, char*, int)), + SLOT(slotReceivedStdout(KProcess*, char*, int))); + connect(&proc, SIGNAL(receivedStderr(KProcess*, char*, int)), + SLOT(slotReceivedStderr(KProcess*, char*, int))); + + proc.start(KProcess::DontCare, KProcess::AllOutput); + + // wait for process to finish + // TODO CL use timeout? + proc.wait(); + + m_addIdentitiesDone = proc.normalExit() && proc.exitStatus() == 0; + return m_addIdentitiesDone; +} + + +void SshAgent::killSshAgent() +{ + if( !m_isRunning || !m_isOurAgent ) + return; + + KProcess proc; + + proc << "kill" << m_pid; + + proc.start(KProcess::DontCare, KProcess::NoCommunication); +} + + +void SshAgent::slotProcessExited(KProcess*) +{ + QRegExp cshPidRx("setenv SSH_AGENT_PID (\\d*);"); + QRegExp cshSockRx("setenv SSH_AUTH_SOCK (.*);"); + + QRegExp bashPidRx("SSH_AGENT_PID=(\\d*).*"); + QRegExp bashSockRx("SSH_AUTH_SOCK=(.*\\.\\d*);.*"); + QStringList m_outputLines = QStringList::split("\n",m_Output); + + QStringList::Iterator it = m_outputLines.begin(); + QStringList::Iterator end = m_outputLines.end(); + for( ; it != end; ++it ) + { + if( m_pid.isEmpty() ) + { + int pos = cshPidRx.search(*it); + if( pos > -1 ) + { + m_pid = cshPidRx.cap(1); + continue; + } + + pos = bashPidRx.search(*it); + if( pos > -1 ) + { + m_pid = bashPidRx.cap(1); + continue; + } + } + + if( m_authSock.isEmpty() ) + { + int pos = cshSockRx.search(*it); + if( pos > -1 ) + { + m_authSock = cshSockRx.cap(1); + continue; + } + + pos = bashSockRx.search(*it); + if( pos > -1 ) + { + m_authSock = bashSockRx.cap(1); + continue; + } + } + } + +} + + +void SshAgent::slotReceivedStdout(KProcess* proc, char* buffer, int buflen) +{ + Q_UNUSED(proc); + + QString output = QString::fromLocal8Bit(buffer, buflen); + m_Output+=output; +} + + +void SshAgent::slotReceivedStderr(KProcess* proc, char* buffer, int buflen) +{ + Q_UNUSED(proc); + + QString output = QString::fromLocal8Bit(buffer, buflen); + m_Output+=output; +} + + +bool SshAgent::startSshAgent() +{ + KProcess proc; + + proc << "ssh-agent"; + + connect(&proc, SIGNAL(processExited(KProcess*)), + SLOT(slotProcessExited(KProcess*))); + connect(&proc, SIGNAL(receivedStdout(KProcess*, char*, int)), + SLOT(slotReceivedStdout(KProcess*, char*, int))); + connect(&proc, SIGNAL(receivedStderr(KProcess*, char*, int)), + SLOT(slotReceivedStderr(KProcess*, char*, int)) ); + + proc.start(KProcess::NotifyOnExit, KProcess::All); + + // wait for process to finish + // TODO CL use timeout? + proc.wait(); + + return (proc.normalExit() && proc.exitStatus() == 0); +} + +#include "sshagent.moc" diff --git a/src/helpers/sshagent.h b/src/helpers/sshagent.h new file mode 100644 index 0000000..f5738fb --- /dev/null +++ b/src/helpers/sshagent.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef SSHAGENT_H +#define SSHAGENT_H + +#include <qobject.h> +#include <qstring.h> +#include <qstringlist.h> + +class KProcess; + + +class SshAgent : public QObject +{ + Q_OBJECT + +public: + SshAgent(QObject* parent = 0, const char* name = 0); + ~SshAgent(); + + bool querySshAgent(); + bool addSshIdentities(bool force=false); + void killSshAgent(); + + bool isRunning() const { return m_isRunning; } + QString pid() const { return m_pid; } + QString authSock() const { return m_authSock; } + +private slots: + void slotProcessExited(KProcess*); + void slotReceivedStdout(KProcess* proc, char* buffer, int buflen); + void slotReceivedStderr(KProcess* proc, char* buffer, int buflen); + +private: + bool startSshAgent(); + + QString m_Output; + + static bool m_isRunning; + static bool m_isOurAgent; + static bool m_addIdentitiesDone; + static QString m_authSock; + static QString m_pid; +}; + + +#endif diff --git a/src/helpers/stringhelper.h b/src/helpers/stringhelper.h new file mode 100644 index 0000000..263f418 --- /dev/null +++ b/src/helpers/stringhelper.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef STRINGHELPER_H +#define STRINGHELPER_H + +#include <qstring.h> +#include <qtextstream.h> + +namespace helpers +{ + +class ByteToString +{ +protected: + +public: + ByteToString(){}; + + QString operator()(long value) + { + char pre = 0; + double v = (double)value; + if (v<0) v=0; + while (v>=1024.0 && pre != 'T') + { + switch (pre) + { + case 'k': + pre = 'M'; + break; + case 'M': + pre = 'G'; + break; + case 'G': + pre = 'T'; + break; + default: + pre = 'k'; + break; + } + v /= 1024.0; + } + return QString("%1 %2Byte").arg(v,0,'f',pre?2:0).arg(pre?QString(QChar(pre)):QString("")); + } +}; + +} + +#endif diff --git a/src/helpers/sub2qt.cpp b/src/helpers/sub2qt.cpp new file mode 100644 index 0000000..1ca0c28 --- /dev/null +++ b/src/helpers/sub2qt.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "sub2qt.h" + +#include "src/svnqt/datetime.hpp" +#include "kglobal.h" +#include "klocale.h" +#include <qmap.h> + +namespace helpers { + +sub2qt::sub2qt() +{ +} + + +sub2qt::~sub2qt() +{ +} + +QString sub2qt::apr_time2qtString(apr_time_t _time) +{ + return DateTime2qtString(_time); +} + +QString sub2qt::DateTime2qtString(const svn::DateTime&_time) +{ + return KGlobal::locale()->formatDateTime(_time); +} + +}; + diff --git a/src/helpers/sub2qt.h b/src/helpers/sub2qt.h new file mode 100644 index 0000000..23eda5f --- /dev/null +++ b/src/helpers/sub2qt.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef HELPERSSUB2QT_H +#define HELPERSSUB2QT_H + +#include "src/svnqt/datetime.hpp" +#include <qdatetime.h> +#include <qstring.h> +#include <svn_time.h> + +namespace helpers { + +/** +@author Rajko Albrecht +*/ +class sub2qt{ +public: + sub2qt(); + ~sub2qt(); + + static QString apr_time2qtString(apr_time_t _time); + static QString DateTime2qtString(const svn::DateTime&_time); +}; + +} +#endif diff --git a/src/icons/CMakeLists.txt b/src/icons/CMakeLists.txt new file mode 100644 index 0000000..e70476e --- /dev/null +++ b/src/icons/CMakeLists.txt @@ -0,0 +1,2 @@ +KDESVN_INSTALL_ICONS(hicolor) + diff --git a/src/icons/hi128-app-kdesvn.png b/src/icons/hi128-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..7f1a221 --- /dev/null +++ b/src/icons/hi128-app-kdesvn.png diff --git a/src/icons/hi16-app-kdesvn.png b/src/icons/hi16-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..fa9c833 --- /dev/null +++ b/src/icons/hi16-app-kdesvn.png diff --git a/src/icons/hi22-app-kdesvn.png b/src/icons/hi22-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..a243579 --- /dev/null +++ b/src/icons/hi22-app-kdesvn.png diff --git a/src/icons/hi32-app-kdesvn.png b/src/icons/hi32-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..0c067cb --- /dev/null +++ b/src/icons/hi32-app-kdesvn.png diff --git a/src/icons/hi48-app-kdesvn.png b/src/icons/hi48-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..4356791 --- /dev/null +++ b/src/icons/hi48-app-kdesvn.png diff --git a/src/icons/hi64-app-kdesvn.png b/src/icons/hi64-app-kdesvn.png Binary files differnew file mode 100644 index 0000000..b5a6a9a --- /dev/null +++ b/src/icons/hi64-app-kdesvn.png diff --git a/src/icons/hisc-app-kdesvn.svgz b/src/icons/hisc-app-kdesvn.svgz Binary files differnew file mode 100644 index 0000000..fc0cdd8 --- /dev/null +++ b/src/icons/hisc-app-kdesvn.svgz diff --git a/src/kdesvn.cpp b/src/kdesvn.cpp new file mode 100644 index 0000000..3f2e269 --- /dev/null +++ b/src/kdesvn.cpp @@ -0,0 +1,450 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "kdesvn.h" +#include "urldlg.h" +#include "kdesvn_part.h" + +#include <qdragobject.h> +#include <kprinter.h> +#include <qpainter.h> +#include <qpaintdevicemetrics.h> +#include <qcursor.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kdeversion.h> +#include <kstatusbar.h> +#include <kaccel.h> +#include <kio/netaccess.h> +#include <kfiledialog.h> +#include <kconfig.h> +#include <kurl.h> +#include <kurldrag.h> +#include <kurlrequesterdlg.h> +#include <khelpmenu.h> +#include <kmenubar.h> +#include <kpopupmenu.h> +#include <kactionclasses.h> +#include <kmessagebox.h> +#include <kstdaccel.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kstandarddirs.h> +#include <kbookmarkmanager.h> +#include <kbookmarkmenu.h> +#include <kdebug.h> +#include <klibloader.h> +#include <kedittoolbar.h> +#include <kkeydialog.h> +#include <kdirselectdialog.h> + +#ifdef TESTING_RC +#include <kcrash.h> +#endif + +kdesvn::kdesvn() + : KParts::MainWindow( 0, "kdesvn" ), + KBookmarkOwner() +{ + m_part = 0; +#ifdef TESTING_RC + setXMLFile(TESTING_RC); + kdDebug()<<"Using test rc file in " << TESTING_RC << endl; + // I hate this crashhandler in development + KCrash::setCrashHandler(0); +#else + setXMLFile("kdesvnui.rc"); +#endif + setStandardToolBarMenuEnabled(true); + // then, setup our actions + setupActions(); + // and a status bar + statusBar()->show(); + + m_bookmarkFile = locateLocal("appdata",QString::fromLatin1("bookmarks.xml"),true); + + m_BookmarkManager = KBookmarkManager::managerForFile(m_bookmarkFile,false); + m_BookmarkManager->setShowNSBookmarks(false); + m_BookmarkManager->setEditorOptions(QString::fromLatin1("KDE Svn"),false); + + m_BookmarksActionmenu = new KActionMenu(i18n("&Bookmarks"),"bookmark",actionCollection(),"bookmarks"); + m_BookmarksActionmenu->setDelayed(false); + m_BookmarksActionmenu->setEnabled(true); + + m_Bookmarkactions = new KActionCollection( this ); + m_Bookmarkactions->setHighlightingEnabled( true ); + connectActionCollection( m_Bookmarkactions ); + + m_pBookmarkMenu = new KBookmarkMenu(m_BookmarkManager,this,m_BookmarksActionmenu->popupMenu(),m_Bookmarkactions,true); +// m_BookmarksActionmenu->plug(menuBar()); + // this routine will find and load our Part. it finds the Part by + // name which is a bad idea usually.. but it's alright in this + // case since our Part is made for this Shell + KLibFactory *factory = KLibLoader::self()->factory("libkdesvnpart"); + + if (factory) + { + if (QCString(factory->className())!="cFactory") { + kdDebug()<<"wrong factory"<<endl; + KMessageBox::error(this, i18n("Could not find our part")); + kapp->quit(); + return; + } + cFactory*cfa = static_cast<cFactory*>(factory); + + // now that the Part is loaded, we cast it to a Part to get + // our hands on it + m_part = static_cast<KParts::ReadOnlyPart *>(cfa->createAppPart(this,"kdesvn_part", this, "kdesvn_part", "KParts::ReadOnlyPart",QStringList())); + + if (m_part) + { + // tell the KParts::MainWindow that this is indeed the main widget + setCentralWidget(m_part->widget()); + + KAction*tmpAction; + tmpAction = new KAction(i18n("Create and open new repository"),"filenew", + KShortcut(),m_part->widget(),SLOT(slotCreateRepo()),actionCollection(),"subversion_create_repo"); + tmpAction->setToolTip(i18n("Create and opens a new local subversion repository")); + tmpAction = new KAction(i18n("Dump repository to file"),"filenew", + KShortcut(),m_part->widget(),SLOT(slotDumpRepo()),actionCollection(),"subversion_dump_repo"); + tmpAction->setToolTip(i18n("Dump a subversion repository to a file")); + tmpAction = new KAction(i18n("Hotcopy a repository"),"filenew", + KShortcut(),m_part->widget(),SLOT(slotHotcopy()),actionCollection(),"subversion_hotcopy_repo"); + tmpAction->setToolTip(i18n("Hotcopy a subversion repository to a new folder")); + tmpAction = new KAction(i18n("Load dump into repository"),"filenew", + KShortcut(),m_part->widget(),SLOT(slotLoaddump()),actionCollection(),"subversion_load_repo"); + tmpAction->setToolTip(i18n("Load a dump file into a repository.")); + tmpAction = new KAction(i18n("Add ssh identities to ssh-agent"),"password", + KShortcut(),m_part,SLOT(slotSshAdd()),actionCollection(),"kdesvn_ssh_add"); + tmpAction->setToolTip(i18n("Force add ssh-identities to ssh-agent for future use.")); + tmpAction = new KAction(i18n("Info about kdesvn part"), "kdesvn", + KShortcut(), m_part, SLOT(showAboutApplication()), actionCollection(), "help_about_kdesvnpart"); + tmpAction->setToolTip(i18n("Shows info about the kdesvn plugin not the standalone app.")); + + /* enable tooltips in statusbar for menu */ + actionCollection()->setHighlightingEnabled(true); + connectActionCollection(actionCollection()); + // and integrate the part's GUI with the shells + createGUI(m_part); + connectActionCollection(m_part->actionCollection()); + } else { + KMessageBox::error(this, i18n("Could not load the part:\n")+KLibLoader::self()->lastErrorMessage()); + kapp->quit(); + return; + } + } + else + { + // if we couldn't find our Part, we exit since the Shell by + // itself can't do anything useful + KMessageBox::error(this, i18n("Could not find our part")+QString(":\n")+KLibLoader::self()->lastErrorMessage()); + kapp->quit(); + // we return here, cause kapp->quit() only means "exit the + // next time we enter the event loop... + return; + } + setAutoSaveSettings(); +} + +void kdesvn::connectActionCollection( KActionCollection *coll ) +{ + if (!coll)return; + connect( coll, SIGNAL( actionStatusText( const QString & ) ), + this, SLOT( changeStatusbar( const QString & ) ) ); + connect( coll, SIGNAL( clearStatusText() ), + this, SLOT( resetStatusBar() ) ); +} + +void kdesvn::disconnectActionCollection( KActionCollection *coll ) +{ + if (!coll)return; +} + +kdesvn::~kdesvn() +{ +} + +void kdesvn::loadRescent(const KURL& url) +{ + load(url,true); +} + +void kdesvn::load(const KURL& url,bool addRescent) +{ + if (m_part) { + bool ret = m_part->openURL(url); + KRecentFilesAction*rac = 0; + if (addRescent) { + KAction * ac = actionCollection()->action("file_open_recent"); + if (ac) { + rac = (KRecentFilesAction*)ac; + } + } + if (!ret) { + changeStatusbar(i18n("Could not open url %1").arg(url.prettyURL())); + if (rac) { + rac->removeURL(url); + } + } else { + resetStatusBar(); + if (rac) { + rac->addURL(url); + } + } + if (rac) { + rac->saveEntries(KGlobal::config(),"recent_files"); + } + } +} + +void kdesvn::setupActions() +{ + KAction*ac; + KStdAction::open(this, SLOT(fileOpen()), actionCollection()); + KStdAction::openNew(this,SLOT(fileNew()),actionCollection()); + ac = KStdAction::close(this,SLOT(fileClose()),actionCollection()); + ac->setEnabled(getMemberList()->count()>1); + KStdAction::quit(kapp, SLOT(quit()), actionCollection()); + + KRecentFilesAction*rac = KStdAction::openRecent(this,SLOT(loadRescent(const KURL&)),actionCollection()); + if (rac) + { + rac->setMaxItems(8); + rac->loadEntries(KGlobal::config(),"recent_files"); + rac->setText(i18n("Recent opened URLs")); + } + + KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection()); + KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection()); + + m_statusbarAction = KStdAction::showStatusbar(this, SLOT(optionsShowStatusbar()), actionCollection()); + + KToggleAction *toggletemp; + toggletemp = new KToggleAction(i18n("Load last opened URL on start"),KShortcut(), + actionCollection(),"toggle_load_last_url"); + toggletemp->setToolTip(i18n("Reload last opened url if no one is given on commandline")); + KConfigGroup cs(KGlobal::config(),"startup"); + toggletemp->setChecked(cs.readBoolEntry("load_last_on_start",false)); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotLoadLast(bool))); +} + +void kdesvn::optionsShowStatusbar() +{ + // this is all very cut and paste code for showing/hiding the + // statusbar + if (m_statusbarAction->isChecked()) + statusBar()->show(); + else + statusBar()->hide(); +} + +void kdesvn::fileClose() +{ + if (m_part) m_part->closeURL(); + if (getMemberList()->count()>1) { + close(); + } else { + enableClose(false); + } +} + +void kdesvn::saveProperties(KConfig *config) +{ + // the 'config' object points to the session managed + // config file. anything you write here will be available + // later when this app is restored + if (!m_part) return; + if (!m_part->url().isEmpty()) { +#if KDE_IS_VERSION(3,1,3) + config->writePathEntry("lastURL", m_part->url().prettyURL()); +#else + config->writeEntry("lastURL", m_part->url().prettyURL()); +#endif + } +} + +void kdesvn::readProperties(KConfig *config) +{ + // the 'config' object points to the session managed + // config file. this function is automatically called whenever + // the app is being restored. read in here whatever you wrote + // in 'saveProperties' + + QString url = config->readPathEntry("lastURL"); + + if (!url.isEmpty() && m_part) + m_part->openURL(KURL(url)); +} + +void kdesvn::fileNew() +{ + // this slot is called whenever the File->New menu is selected, + // the New shortcut is pressed (usually CTRL+N) or the New toolbar + // button is clicked + + // create a new window + (new kdesvn)->show(); + enableClose(true); +} + +void kdesvn::fileOpen() +{ + KURL url = UrlDlg::getURL(this); + if (!url.isEmpty()) + load(url,true); +} + +void kdesvn::changeStatusbar(const QString& text) +{ + // display the text on the statusbar + statusBar()->message(text); +} + +void kdesvn::resetStatusBar() +{ + statusBar()->message(i18n("Ready")); +} + +void kdesvn::openBookmarkURL (const QString &_url) +{ + if (!_url.isEmpty() && m_part) + load(_url,false); +} + +QString kdesvn::currentURL () const +{ + if (!m_part) return ""; + return m_part->url().prettyURL(); +} + +void kdesvn::enableClose(bool how) +{ + KAction * ac; + if ( (ac=actionCollection()->action("file_close"))) { + ac->setEnabled(how); + } +} + +/*! + \fn kdesvn::slotUrlOpened(bool) + */ +void kdesvn::slotUrlOpened(bool how) +{ + enableClose(how); +} + + +/*! + \fn kdesvn::optionsConfigureToolbars() + */ +void kdesvn::optionsConfigureToolbars() +{ +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + saveMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + saveMainWindowSettings(KGlobal::config() ); +# endif +#else + saveMainWindowSettings(KGlobal::config() ); +#endif + + // use the standard toolbar editor + KEditToolbar dlg(factory()); + connect(&dlg, SIGNAL(newToolbarConfig()), + this, SLOT(applyNewToolbarConfig())); + dlg.exec(); +} + + +/*! + \fn kdesvn::applyNewToolbarConfig() + */ +void kdesvn::applyNewToolbarConfig() +{ +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + applyMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + applyMainWindowSettings(kdesvnPart::config()); +# endif +#else + applyMainWindowSettings(kdesvnPart::config()); +#endif +} + +void kdesvn::optionsConfigureKeys() +{ + KKeyDialog kdlg(true,m_part->widget()); + kdlg.insert(actionCollection()); + kdlg.insert(m_part->actionCollection()); + bool b = kdlg.configure(true); + if (b) { + kdlg.commitChanges(); + } +} + + +/*! + \fn kdesvn::queryExit() + */ +bool kdesvn::queryExit() +{ + if (m_part) { + KConfigGroup cs(KGlobal::config(),"startup"); +#if KDE_IS_VERSION(3,1,3) + cs.writePathEntry("lastURL", m_part->url().prettyURL()); +#else + cs.writeEntry("lastURL", m_part->url().prettyURL()); +#endif + } + return KParts::MainWindow::queryExit(); +} + + +/*! + \fn kdesvn::checkReload() + */ +void kdesvn::checkReload() +{ + KConfigGroup cs(KGlobal::config(),"startup"); + if (!cs.readBoolEntry("load_last_on_start",false)) + return; + + QString url = cs.readPathEntry("lastURL"); + + if (!url.isEmpty() && m_part) + load(KURL(url),false); +} + + +/*! + \fn kdesvn::slotLoadLast(bool) + */ +void kdesvn::slotLoadLast(bool how) +{ + KConfigGroup cs(KGlobal::config(),"startup"); + cs.writeEntry("load_last_on_start",how); +} + +#include "kdesvn.moc" diff --git a/src/kdesvn.desktop b/src/kdesvn.desktop new file mode 100644 index 0000000..a3b58dd --- /dev/null +++ b/src/kdesvn.desktop @@ -0,0 +1,22 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=kdesvn +GenericName=SVN client +GenericName[de]=Graphische Oberfläche für SVN +GenericName[es]=Cliente SVN +GenericName[lt]=SVN klientas +Exec=kdesvn %i %m -caption "%c" +Icon=kdesvn +Type=Application +DocPath=kdesvn/index.html +Comment=A Subversion client for KDE +Comment[de]=Ein Subversionclient für KDE +Comment[nl]=Een Subversion-client voor KDE +Comment[es]=Un cliente de Subversion para KDE +Comment[lt]=Subversion klientas skirtas KDE +Terminal=false +MimeType=inode/directory; +ServiceTypes=KParts/ReadOnlyPart,Browser/View +X-KDE-BrowserView-Args=DetailedList +X-KDE-Library=libkdesvnpart +Categories=Qt;KDE;Development; diff --git a/src/kdesvn.h b/src/kdesvn.h new file mode 100644 index 0000000..203f2d6 --- /dev/null +++ b/src/kdesvn.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef _KDESVN_H_ +#define _KDESVN_H_ + +#include "kdesvn-config.h" + +#include <kapplication.h> +#include <kparts/mainwindow.h> +#include <qtimer.h> +#include <kbookmarkmanager.h> + +class KURL; +class KAction; +class KActionMenu; +class KToggleAction; +class KBookmarkMenu; + +/** + * This class serves as the main window for kdesvn. It handles the + * menus, toolbars, and status bars. + * + * @short Main window class + * @author Rajko Albrecht <ral@alwins-world.de> + * @version $Rev: 1229 $ + */ +class kdesvn : public KParts::MainWindow,public KBookmarkOwner +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + kdesvn(); + + /** + * Default Destructor + */ + virtual ~kdesvn(); + + virtual void openBookmarkURL (const QString &_url); + virtual QString currentURL () const; + void checkReload(); + +protected: + /** + * This function is called when it is time for the app to save its + * properties for session management purposes. + */ + void saveProperties(KConfig *); + + /** + * This function is called when this app is restored. The KConfig + * object points to the session management config file that was saved + * with @ref saveProperties + */ + void readProperties(KConfig *); + virtual bool queryExit(); + void enableClose(bool how); + + +public slots: + virtual void slotUrlOpened(bool); + virtual void loadRescent(const KURL&); + virtual void load(const KURL&,bool); + +private slots: + void fileOpen(); + void fileNew(); + void fileClose(); + void optionsShowStatusbar(); + void changeStatusbar(const QString&); + void resetStatusBar(); + +private: + void setupAccel(); + void setupActions(); + void connectActionCollection( KActionCollection *coll ); + void disconnectActionCollection( KActionCollection *coll ); + + KActionMenu *m_FileMenu; + QString m_bookmarkFile; + KBookmarkManager * m_BookmarkManager; + KActionMenu* m_BookmarksActionmenu; + KActionCollection*m_Bookmarkactions; + KBookmarkMenu * m_pBookmarkMenu; + KParts::ReadOnlyPart *m_part; + KToggleAction *m_statusbarAction; + +protected slots: + virtual void optionsConfigureToolbars(); + virtual void optionsConfigureKeys(); + virtual void applyNewToolbarConfig(); + virtual void slotLoadLast(bool); +}; + +#endif // _KDESVN_H_ diff --git a/src/kdesvn.lsm b/src/kdesvn.lsm new file mode 100644 index 0000000..8efa3e9 --- /dev/null +++ b/src/kdesvn.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: kdesvn -- Some description +Version: 0.5.0 +Entered-date: +Description: +Keywords: KDE Qt Subversion +Author: Rajko Albrecht <ral@alwins-world.de> +Maintained-by: Rajko Albrecht <ral@alwins-world.de> +Home-page: +Alternate-site: +Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils + xxxxxx kdesvn-0.5.0.tar.gz + xxx kdesvn-0.5.0.lsm +Platform: Linux. Needs KDE +Copying-policy: GPL +End diff --git a/src/kdesvn_events.cpp b/src/kdesvn_events.cpp new file mode 100644 index 0000000..4536d2a --- /dev/null +++ b/src/kdesvn_events.cpp @@ -0,0 +1,7 @@ +#include "kdesvn_events.h" +#include "eventnumbers.h" + +FillCacheStatusEvent::FillCacheStatusEvent(Q_LLONG current,Q_LLONG max) + :QCustomEvent(EVENT_LOGCACHE_STATUS),m_current(current),m_max(max) +{ +} diff --git a/src/kdesvn_events.h b/src/kdesvn_events.h new file mode 100644 index 0000000..509125e --- /dev/null +++ b/src/kdesvn_events.h @@ -0,0 +1,17 @@ +#ifndef __KDESVN_EVENTS_H +#define __KDESVN_EVENTS_H + +#include <qevent.h> +#include "src/svnqt/svnqt_defines.hpp" + +class FillCacheStatusEvent:public QCustomEvent +{ + public: + FillCacheStatusEvent(Q_LLONG current,Q_LLONG max); + Q_LLONG current()const{return m_current;} + Q_LLONG max()const{return m_max;} + private: + Q_LLONG m_current,m_max; +}; + +#endif diff --git a/src/kdesvn_part.cpp b/src/kdesvn_part.cpp new file mode 100644 index 0000000..83cd0d0 --- /dev/null +++ b/src/kdesvn_part.cpp @@ -0,0 +1,451 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "kdesvn_part.h" +#include "src/settings/kdesvnsettings.h" +#include "settings/displaysettings_impl.h" +#include "settings/dispcolorsettings_impl.h" +#include "settings/revisiontreesettingsdlg_impl.h" +#include "settings/diffmergesettings_impl.h" +#include "settings/subversionsettings_impl.h" +#include "settings/cmdexecsettings_impl.h" +#include "kdesvnview.h" +#include "commandline_part.h" +#include "src/svnqt/version_check.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/ktranslateurl.h" +#include "helpers/sshagent.h" + +#include <kinstance.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kfiledialog.h> +#include <kdebug.h> +#include <kbugreport.h> +#include <kxmlguifactory.h> +#include <kaboutapplication.h> +#include <kapp.h> +#include <kconfigdialog.h> +#include <kaboutdata.h> +#include <klocale.h> + +#include <qcursor.h> +#include <qpopupmenu.h> + +//K_EXPORT_COMPONENT_FACTORY( libkdesvnpart, kdesvnPartFactory ) + +extern "C" { KDESVN_EXPORT void *init_libkdesvnpart() { return new kdesvnPartFactory; } } + +static const char version[] = VERSION; +QString kdesvnPart::m_Extratext = ""; + +static const char description[] = + I18N_NOOP("A Subversion Client for KDE (dynamic Part component)"); + +kdesvnPart::kdesvnPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name , const QStringList&) + : KParts::ReadOnlyPart(parent, name) +{ + init(parentWidget,widgetName,false); +} + +kdesvnPart::kdesvnPart(QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name,bool ownapp, const QStringList&) + : KParts::ReadOnlyPart(parent, name) +{ + init(parentWidget,widgetName,ownapp); +} + +void kdesvnPart::init( QWidget *parentWidget, const char *widgetName,bool full) +{ + m_aboutDlg = 0; + KGlobal::locale()->insertCatalogue("kdesvn"); + // we need an instance + setInstance( kdesvnPartFactory::instance() ); + m_browserExt = new KdesvnBrowserExtension( this ); + + // this should be your custom internal widget + m_view = new kdesvnView(actionCollection(),parentWidget,widgetName,full); + + // notify the part that this is our internal widget + setWidget(m_view); + + // create our actions + setupActions(); + // set our XML-UI resource file +#ifdef TESTING_PARTRC + setXMLFile(TESTING_PARTRC); + kdDebug()<<"Using test rc file in " << TESTING_PARTRC << endl; +#else + setXMLFile("kdesvn_part.rc"); +#endif + connect(m_view,SIGNAL(sigShowPopup(const QString&,QWidget**)),this,SLOT(slotDispPopup(const QString&,QWidget**))); + connect(m_view,SIGNAL(sigSwitchUrl(const KURL&)),this,SLOT(openURL(const KURL&))); + connect(this,SIGNAL(refreshTree()),m_view,SLOT(refreshCurrentTree())); + connect(m_view,SIGNAL(setWindowCaption(const QString&)),this,SIGNAL(setWindowCaption(const QString&))); + connect(m_view,SIGNAL(sigUrlChanged( const QString&)),this,SLOT(slotUrlChanged(const QString&))); + connect(this,SIGNAL(settingsChanged()),widget(),SLOT(slotSettingsChanged())); + + m_browserExt->setPropertiesActionEnabled(false); +} + +kdesvnPart::~kdesvnPart() +{ + kdesvnPartFactory::instance()->config()->sync(); +} + +void kdesvnPart::slotUrlChanged(const QString&url) +{ + m_url = url; +} + +bool kdesvnPart::openFile() +{ + m_view->openURL(m_url); + // just for fun, set the status bar + emit setStatusBarText( m_url.prettyURL() ); + + return true; +} + +bool kdesvnPart::openURL(const KURL&url) +{ + + KURL _url = helpers::KTranslateUrl::translateSystemUrl(url); + + _url.setProtocol(svn::Url::transformProtokoll(_url.protocol())); + + if (!_url.isValid()||!closeURL()) { + return false; + } + m_url = _url; + emit started(0); + bool ret = m_view->openURL(m_url); + if (ret) { + emit completed(); + emit setWindowCaption(url.prettyURL()); + } + return ret; +} + +void kdesvnPart::slotFileProperties() +{ +} + +void kdesvnPart::slotDispPopup(const QString&name,QWidget**target) +{ + *target = hostContainer(name); +} + +KAboutData* kdesvnPart::createAboutData() +{ + m_Extratext = QString(I18N_NOOP("Built with Subversion library: %1\n")).arg(svn::Version::linked_version()); + m_Extratext+=QString(I18N_NOOP("Running Subversion library: %1")).arg(svn::Version::running_version()); + + KAboutData*about = new KAboutData("kdesvnpart", I18N_NOOP("kdesvn Part"), version, description, + KAboutData::License_GPL, "(C) 2005-2007 Rajko Albrecht",0, + 0, "ral@alwins-world.de"); + about->addAuthor( "Rajko Albrecht", 0, "ral@alwins-world.de" ); + about->setOtherText(m_Extratext); + about->setHomepage("http://kdesvn.alwins-world.de/"); + about->setBugAddress("kdesvn-bugs@alwins-world.de"); + about->setTranslator(I18N_NOOP("kdesvn: NAME OF TRANSLATORS\\nYour names"), + I18N_NOOP("kdesvn: EMAIL OF TRANSLATORS\\nYour emails")); + return about; +} + + +/*! + \fn kdesvnPart::setupActions() + */ +void kdesvnPart::setupActions() +{ + KToggleAction *toggletemp; + + toggletemp = new KToggleAction(i18n("Logs follow node changes"),KShortcut(), + actionCollection(),"toggle_log_follows"); + toggletemp->setChecked(Kdesvnsettings::log_follows_nodes()); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotLogFollowNodes(bool))); + + toggletemp = new KToggleAction(i18n("Display ignored files"),KShortcut(), + actionCollection(),"toggle_ignored_files"); + toggletemp->setChecked(Kdesvnsettings::display_ignored_files()); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotDisplayIgnored(bool))); + + + toggletemp = new KToggleAction(i18n("Display unknown files"),KShortcut(), + actionCollection(),"toggle_unknown_files"); + toggletemp->setChecked(Kdesvnsettings::display_unknown_files()); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotDisplayUnkown(bool))); + + toggletemp = new KToggleAction(i18n("Hide unchanged files"),KShortcut(), + actionCollection(),"toggle_hide_unchanged_files"); + toggletemp->setChecked(Kdesvnsettings::hide_unchanged_files()); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotHideUnchanged(bool))); + + toggletemp = new KToggleAction(i18n("Work online"),KShortcut(), + actionCollection(),"toggle_network"); + toggletemp->setChecked(Kdesvnsettings::network_on()); + connect(toggletemp,SIGNAL(toggled(bool)),this,SLOT(slotEnableNetwork(bool))); + + kdDebug()<<"Appname = " << (QString)kapp->instanceName() << endl; + + KAction * t = KStdAction::preferences(this, SLOT(slotShowSettings()), actionCollection(),"kdesvnpart_pref"); + t->setText(i18n("&Configure %1...").arg("Kdesvn")); + if (QString(kapp->instanceName())!=QString("kdesvn")) { + (void)new KAction(i18n("&About kdesvn part"), "kdesvn", 0, this, SLOT(showAboutApplication()), actionCollection(), "help_about_kdesvnpart"); + (void)new KAction(i18n("Kdesvn &Handbook"), "help", 0, this, SLOT(appHelpActivated()), actionCollection(), "help_kdesvn"); + (void)new KAction(i18n("Send Bugreport for kdesvn"), 0, 0, this, SLOT(reportBug()), actionCollection(), "report_bug"); + } + actionCollection()->setHighlightingEnabled(true); +} + +void kdesvnPart::slotSshAdd() +{ + SshAgent ag; + ag.addSshIdentities(true); +} + +/*! + \fn kdesvnPart::slotLogFollowNodes(bool) + */ +void kdesvnPart::slotLogFollowNodes(bool how) +{ + Kdesvnsettings::setLog_follows_nodes(how); + Kdesvnsettings::writeConfig(); +} + + +/*! + \fn kdesvnPart::slotDiplayIgnored(bool) + */ +void kdesvnPart::slotDisplayIgnored(bool how) +{ + Kdesvnsettings::setDisplay_ignored_files(how); + Kdesvnsettings::writeConfig(); + emit refreshTree(); +} + + +/*! + \fn kdesvnPart::slotDisplayUnknown(bool) + */ +void kdesvnPart::slotDisplayUnkown(bool how) +{ + Kdesvnsettings::setDisplay_unknown_files(how); + Kdesvnsettings::writeConfig(); + emit refreshTree(); +} + +/*! + \fn kdesvnPart::slotHideUnchanged(bool) + */ +void kdesvnPart::slotHideUnchanged(bool how) +{ + Kdesvnsettings::setHide_unchanged_files(how); + Kdesvnsettings::writeConfig(); + emit refreshTree(); +} + +void kdesvnPart::slotEnableNetwork(bool how) +{ + Kdesvnsettings::setNetwork_on(how); + Kdesvnsettings::writeConfig(); + emit settingsChanged(); +} + +/*! + \fn kdesvnPart::closeURL() + */ +bool kdesvnPart::closeURL() +{ + m_url=KURL(); + m_view->closeMe(); + emit setWindowCaption(""); + return true; +} + +KdesvnBrowserExtension::KdesvnBrowserExtension( kdesvnPart *p ) + : KParts::BrowserExtension( p, "KdesvnBrowserExtension" ) +{ + KGlobal::locale()->insertCatalogue("kdesvn"); +} + +KdesvnBrowserExtension::~KdesvnBrowserExtension() +{ + +} + + +void KdesvnBrowserExtension::setPropertiesActionEnabled(bool enabled) +{ + emit enableAction("properties", enabled); +} + + +void KdesvnBrowserExtension::properties() +{ + static_cast<kdesvnPart*>(parent())->slotFileProperties(); +} + + +/*! + \fn kdesvnPart::reportBug() + */ +void kdesvnPart::reportBug() +{ + KBugReport dlg(m_view, true, createAboutData()); + dlg.exec(); +} + +/*! + \fn kdesvnPart::showAboutApplication() + */ +void kdesvnPart::showAboutApplication() +{ + if (!m_aboutDlg) m_aboutDlg = new KAboutApplication(createAboutData(), (QWidget *)0, (const char *)0, false); + if(m_aboutDlg == 0) + return; + if(!m_aboutDlg->isVisible()) + m_aboutDlg->show(); + else + m_aboutDlg->raise(); +} + + +/*! + \fn kdesvnPart::appHelpActivated() + */ +void kdesvnPart::appHelpActivated() +{ + kapp->invokeHelp(QString::null, "kdesvn"); +} + + +/*! + \fn kdesvnPart::slotShowSettings() + */ +void kdesvnPart::slotShowSettings() +{ + if (KConfigDialog::showDialog("kdesvnpart_settings")) { + return; + } + KConfigDialog *dialog = new KConfigDialog(widget(), + "kdesvnpart_settings", + Kdesvnsettings::self(), + KDialogBase::IconList); + dialog->setHelp("setup","kdesvn"); + dialog->addPage(new DisplaySettings_impl(0,"general_items"), + i18n("General"),"configure",i18n("General"),true); + dialog->addPage(new SubversionSettings_impl(0,"subversion_items"), + i18n("Subversion"),"kdesvn",i18n("Subversion Settings"),true); + dialog->addPage(new DiffMergeSettings_impl(0,"diffmerge_items"), + i18n("Diff & Merge"),"kdesvnmerge",i18n("Settings for diff and merge"),true); + dialog->addPage(new DispColorSettings_impl(0,"color_items"), + i18n("Colors"),"colorize",i18n("Color Settings"),true); + dialog->addPage(new RevisiontreeSettingsDlg_impl(0,"revisiontree_items"), + i18n("Revision tree"),"configure",i18n("Revision tree Settings"),true); + dialog->addPage(new CmdExecSettings_impl(0,"cmdexec_items"), + "KIO/"+i18n("Commandline"),"terminal",i18n("Settings for commandline and KIO execution"),true); + + connect(dialog,SIGNAL(settingsChanged()),this,SLOT(slotSettingsChanged())); + dialog->show(); +} + + +/*! + \fn kdesvnPart::slotSettingsChanged() + */ +void kdesvnPart::slotSettingsChanged() +{ + KAction * temp; + temp = actionCollection()->action("toggle_log_follows"); + if (temp) { + ((KToggleAction*)temp)->setChecked(Kdesvnsettings::log_follows_nodes()); + } + temp = actionCollection()->action("toggle_ignored_files"); + if (temp) { + ((KToggleAction*)temp)->setChecked(Kdesvnsettings::display_ignored_files()); + } +#if 0 + /// not needed this momenta + temp = actionCollection()->action("toggle_unknown_files"); + if (temp) { + ((KToggleAction*)temp)->setChecked(kdesvnPart_Prefs::self()->mdisp_unknown_files); + } +#endif + emit settingsChanged(); +} + +/* + * we may not use generic factory 'cause we make some specials */ +KInstance* cFactory::s_instance = 0L; +KAboutData* cFactory::s_about = 0L; +commandline_part* cFactory::s_cline = 0L; + +KParts::Part* cFactory::createPartObject( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *classname, const QStringList &args ) +{ + Q_UNUSED(classname); + // Create an instance of our Part + return new kdesvnPart( parentWidget, widgetName, parent, name, args ); +} + +KParts::Part* cFactory::createAppPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *classname, const QStringList &args ) +{ + Q_UNUSED(classname); + // Create an instance of our Part + kdesvnPart* obj = new kdesvnPart( parentWidget, widgetName, parent, name, false, args); + emit objectCreated( obj ); + return obj; +} + +cFactory::~cFactory() +{ + delete s_instance; + delete s_about; + delete s_cline; + + s_instance = 0L; + s_cline = 0L; +} + +KInstance* cFactory::instance() +{ + if( !s_instance ) { + s_about = kdesvnPart::createAboutData(); + s_instance = new KInstance(s_about); + } + return s_instance; +} + +commandline_part*cFactory::createCommandIf(QObject*parent,const char*name, KCmdLineArgs *args) +{ + if (!s_cline) { + // no emit of creation - we will delete this object in destructor + s_cline = new commandline_part(parent,name,args); + } + return s_cline; +} + +#include "kdesvn_part.moc" diff --git a/src/kdesvn_part.h b/src/kdesvn_part.h new file mode 100644 index 0000000..44dce7a --- /dev/null +++ b/src/kdesvn_part.h @@ -0,0 +1,146 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _KDESVNPART_H_ +#define _KDESVNPART_H_ + +#include "kdesvn-config.h" + +#include <kparts/part.h> +#include <kparts/genericfactory.h> +#include <kparts/factory.h> +#include <kparts/statusbarextension.h> +#include <kparts/browserextension.h> + +class kdesvnView; +class QPainter; +class KURL; +class KdesvnBrowserExtension; +class KAboutApplication; + +/** + * This is a "Part". It that does all the real work in a KPart + * application. + * + * @short Main Part + * @author Rajko Albrecht <rajko.albrecht@tecways.com> + * @version 0.1 + */ +class KDESVN_EXPORT kdesvnPart : public KParts::ReadOnlyPart +{ + Q_OBJECT +public: + /** + * Default constructor + */ + kdesvnPart(QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList&); + + kdesvnPart(QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name,bool ownapp, const QStringList&); + + /** + * Destructor + */ + virtual ~kdesvnPart(); + virtual bool closeURL(); + static KAboutData* createAboutData(); + +signals: + void refreshTree(); + void settingsChanged(); + +public slots: + virtual void slotDispPopup(const QString&,QWidget**target); + virtual void slotFileProperties(); + virtual bool openURL(const KURL&); + virtual void slotSshAdd(); + +protected: + /** + * This must be implemented by each part + */ + virtual bool openFile(); + virtual void setupActions(); + KAboutApplication* m_aboutDlg; + + void init(QWidget *parentWidget, const char *widgetName,bool full); + +protected slots: + virtual void slotLogFollowNodes(bool); + virtual void slotDisplayIgnored(bool); + virtual void slotDisplayUnkown(bool); + virtual void slotUrlChanged(const QString&); + void reportBug(); + void showAboutApplication(); + void appHelpActivated(); + virtual void slotShowSettings(); + +private: + kdesvnView *m_view; + KdesvnBrowserExtension*m_browserExt; + static QString m_Extratext; +protected slots: + void slotSettingsChanged(); +protected slots: + virtual void slotHideUnchanged(bool); + virtual void slotEnableNetwork(bool); +}; + +class commandline_part; +class KCmdLineArgs; + +/* we make it ourself 'cause we will enhance a little bit! */ +class KDESVN_EXPORT cFactory : public KParts::Factory +{ + Q_OBJECT +public: + cFactory():KParts::Factory(){} + virtual ~cFactory(); + virtual KParts::Part* createPartObject( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *classname, const QStringList &args ); + virtual KParts::Part* createAppPart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *classname, const QStringList &args ); + virtual commandline_part*createCommandIf(QObject*parent,const char*name, KCmdLineArgs *args); + static KInstance* instance(); + +private: + static KInstance* s_instance; + static KAboutData* s_about; + static commandline_part*s_cline; +}; + +typedef cFactory kdesvnPartFactory; + +class KPARTS_EXPORT KdesvnBrowserExtension : public KParts::BrowserExtension +{ + Q_OBJECT +public: + KdesvnBrowserExtension( kdesvnPart * ); + virtual ~KdesvnBrowserExtension(); + void setPropertiesActionEnabled(bool enabled); + +public slots: + void properties(); +}; + +#endif // _KDESVNPART_H_ diff --git a/src/kdesvn_part.rc b/src/kdesvn_part.rc new file mode 100644 index 0000000..5e2eaef --- /dev/null +++ b/src/kdesvn_part.rc @@ -0,0 +1,243 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kdesvn_part" version="17"> +<MenuBar> + <Menu noMerge="1" name="settings"> + <Action name="kdesvnpart_pref" /> + <Menu name="quicksettings"> + <text>Quick settings</text> + <Action name="toggle_log_follows" /> + <Action name="toggle_ignored_files" /> + <Action name="toggle_unknown_files" /> + <Action name="toggle_hide_unchanged_files" /> + <Action name="toggle_network"/> + </Menu> + </Menu> + <Menu name="subversion_main" > + <text>Subversion</text> + <Menu name="subversion_general" > + <text>General</text> + <Action name="make_svn_log_full" /> + <Action name="make_svn_log" /> + <Action name="make_svn_tree" /> + <Action name="make_svn_partialtree" /> + <Action name="make_svn_info" /> + <Action name="make_revisions_diff" /> + <Action name="make_last_change" /> + <Action name="make_svn_itemsdiff" /> + <Action name="make_svn_merge" /> + <Separator/> + <Action name="make_svn_blame" /> + <Action name="make_svn_range_blame" /> + <Action name="make_svn_cat" /> + <Action name="make_revisions_cat" /> + <Separator/> + <Action name="make_svn_rename" /> + <Action name="make_svn_copy" /> + <Action name="make_svn_remove" /> + <Action name="make_svn_mkdir" /> + <Action name="make_import_dirs_into_current" /> + <Separator/> + <Action name="make_svn_checkout" /> + <Action name="make_svn_export" /> + <Action name="make_svn_export_current" /> + <Separator/> + <Action name="make_svn_lock"/> + <Action name="make_svn_unlock"/> + </Menu> + <Menu name="subversion_working_copy" > + <text>Working copy</text> + <Action name="make_svn_headupdate" /> + <Action name="make_svn_revupdate" /> + <Action name="make_svn_commit" /> + <Action name="make_svn_basediff" /> + <Action name="make_svn_headdiff" /> + <Action name="make_svn_property" /> + <Separator/> + <Action name="make_svn_add" /> + <Action name="make_svn_addrec" /> + <Action name="make_check_unversioned" /> + <Action name="make_svn_revert" /> + <Action name="make_try_resolve"/> + <Action name="make_resolved" /> + <Action name="make_svn_merge_revisions" /> + <Action name="make_svn_ignore" /> + <Separator/> + <Action name="make_cleanup" /> + <Action name="make_svn_switch" /> + <Action name="make_svn_relocate" /> + <Separator/> + <Action name="make_switch_to_repo" /> + <Action name="make_check_updates" /> + </Menu> + <Menu name="subversion_repo" > + <text>Repository</text> + <Action name="make_svn_checkout_current" /> + <Separator/> + <Action name="switch_browse_revision" /> + </Menu> + <Separator/> + <Menu name="generic_view"> + <text>View</text> + <Action name="make_view_refresh" /> + <Action name="view_unfold_tree" /> + <Action name="view_fold_tree" /> + </Menu> + <Separator/> + <Menu name="log_cache"> + <text>Logcache</text> + <Action name="update_log_cache"/> + </Menu> + <Separator/> + </Menu> + <Menu name="help"><text>&Help</text> + <Separator/> + <Action name="help_about_kdesvnpart" /> + <Action name="help_kdesvn" /> + <Action name="report_bug" /> + </Menu> +</MenuBar> + <Menu name="local_context_single_conflicted"> + <text>Actions</text> + <Action name="make_resolved" /> + <Action name="make_try_resolve"/> + </Menu> + <Menu name="local_context_single_versioned" > + <text>Actions</text> + <Action name="make_svn_headupdate"/> + <Action name="make_svn_commit" /> + <Action name="make_svn_log_full" /> + <Action name="make_svn_basediff" /> + <Action name="make_svn_headdiff" /> + <Action name="make_last_change" /> + <Action name="make_svn_cat" /> + <Separator/> + <Action name="make_svn_lock" /> + <Action name="make_svn_unlock" /> + <Separator/> + <Action name="make_svn_rename" /> + <Action name="make_svn_remove" /> + <Separator/> + </Menu> + <Menu name="local_context_single_versioned_dir"> + <Action name="make_svn_headupdate"/> + <Action name="make_svn_commit" /> + <Action name="make_svn_log_full" /> + <Action name="make_svn_basediff" /> + <Action name="make_svn_headdiff" /> + <Action name="make_last_change" /> + <Separator/> + <Action name="make_cleanup" /> + <Separator/> + <Action name="make_svn_remove" /> + <Action name="make_svn_rename" /> + <Action name="make_svn_mkdir" /> + <Action name="make_view_refresh" /> + </Menu> + <Menu name="local_context_single_unversioned" > + <text>Actions</text> + <Action name="make_svn_add"/> + <Action name="make_svn_ignore"/> + <Action name="make_svn_remove" /> + <Separator/> + </Menu> + <Menu name="local_context_multi" > + <text>Actions</text> + <Action name="make_svn_headupdate"/> + <Action name="make_svn_commit" /> + <Action name="make_svn_basediff" /> + <Action name="make_svn_headdiff" /> + <Action name="make_svn_itemsdiff" /> + <Separator/> + <Action name="make_view_refresh" /> + </Menu> + <Menu name="remote_context_single" > + <Action name="make_svn_log_full" /> + <Action name="make_svn_blame" /> + <Action name="make_svn_cat" /> + <Action name="get_svn_property" /> + <Action name="make_last_change" /> + <Separator/> + <Action name="make_svn_lock" /> + <Action name="make_svn_unlock" /> + <Separator/> + <Action name="make_svn_rename" /> + <Action name="make_svn_remove" /> + <Separator/> + </Menu> + <Menu name="remote_context_single_dir" > + <Action name="make_svn_log_full" /> + <Action name="make_svn_checkout_current" /> + <Action name="make_svn_export_current" /> + <Action name="get_svn_property" /> + <Action name="make_last_change" /> + <Separator/> + <Action name="make_svn_mkdir" /> + <Action name="make_svn_rename" /> + <Action name="make_svn_remove" /> + <Separator/> + <Action name="make_view_refresh" /> + </Menu> + <Menu name="remote_context_multi" > + <Action name="make_svn_log_full" /> + <Action name="make_svn_checkout_current" /> + <Action name="make_svn_export_current" /> + <Action name="make_svn_blame" /> + <Action name="make_svn_cat" /> + <Separator/> + <Action name="make_svn_itemsdiff" /> + <Separator/> + <Action name="make_svn_remove" /> + <Action name="make_view_refresh" /> + </Menu> + <Menu name="local_general"> + <Action name="make_svn_headupdate" /> + <Action name="make_svn_commit" /> + <Separator/> + <Action name="make_svn_mkdir" /> + <Action name="make_view_refresh" /> + <Action name="make_cleanup" /> + </Menu> + <Menu name="remote_general"> + <Action name="make_svn_mkdir" /> + <Action name="make_svn_itemsdiff" /> + <Separator/> + <Action name="make_svn_checkout_current" /> + <Action name="make_svn_export_current" /> + <Separator/> + <Action name="make_view_refresh" /> + </Menu> + <Menu name="empty_general" > + <Action name="file_open" /> + <Action name="open_remote_repository" /> + <Separator/> + <Action name="bookmarks" /> + <Separator/> + <Action name="make_svn_checkout" /> + <Action name="make_svn_export" /> + </Menu> + <ToolBar name="subversionToolBar"> + <text>Subversion toolbar</text> + <Action name="make_svn_headupdate" /> + <Action name="make_svn_commit" /> + <Action name="make_check_updates" /> + <Separator name="separator_3" /> + <Action name="make_svn_log_full" /> + <Action name="make_svn_info" /> + <Action name="make_svn_blame" /> + <Separator name="separator_2" /> + <Action name="make_svn_add" /> + <Action name="make_check_unversioned" /> + <Action name="make_svn_remove" /> + <Action name="make_svn_merge_revisions" /> + <Separator name="separator_1" /> + <Action name="make_svn_checkout" /> + <Action name="make_svn_export" /> + <Separator name="separator_0" /> + <Action name="make_view_refresh" /> + </ToolBar> + <ToolBar name="mainToolBar" > + <text>Main Toolbar</text> + <Action name="file_open" /> + <Action name="file_close" /> + </ToolBar> +</kpartgui> diff --git a/src/kdesvnd/CMakeLists.txt b/src/kdesvnd/CMakeLists.txt new file mode 100644 index 0000000..fee835f --- /dev/null +++ b/src/kdesvnd/CMakeLists.txt @@ -0,0 +1,55 @@ +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/src/svnqt) +FILE(GLOB hdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") +SET(kded_kdesvnd_src + kdesvnd_dcop.cpp + ${hdr} + ) + +KDE3_ADD_MOC_FILES(kded_kdesvnd_src kdesvnd_dcop.h) + +KDE3_ADD_DCOP_SKELS(kded_kdesvnd_src + kdesvnd_dcop.h) + +KDE3_ADD_KPART(kded_kdesvnd ${kded_kdesvnd_src}) + +TARGET_LINK_LIBRARIES(kded_kdesvnd + svnqt + ksvnwidgets + kdesvnhelpers + kdesvncfgreader + ${QT_AND_KDECORE_LIBS} ${KDE3_KIO_LIBRARY} ${KDE3_DCOP_LIBRARY} + ${KDE3_UI_LIBRARY} ${KDE3_WALLET_LIBRARY} + ${KDE3_KINIT_KDED_LIBRARY}) + +SET_TARGET_PROPERTIES(kded_kdesvnd + PROPERTIES + LINK_FLAGS "${LINK_NO_UNDEFINED} ${_BASE_LDADD} ${APR_EXTRA_LIBFLAGS} ${APU_EXTRA_LIBFLAGS} -avoid-version -module") + +INSTALL(TARGETS kded_kdesvnd + RUNTIME DESTINATION ${BIN_INSTALL_DIR} + LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR}) + +KDESVN_GENERATE_LIBTOOL_FILE(kded_kdesvnd) + +IF(KDE3_KDECONFIG_EXECUTABLE) + EXECUTE_PROCESS(COMMAND ${KDE3_KDECONFIG_EXECUTABLE} "--version" OUTPUT_VARIABLE output) + STRING(REGEX MATCH "KDE: [0-9]+\\.[0-9]+\\.[0-9]+" KDEVERSION "${output}") + STRING(REGEX REPLACE "^KDE: " "" KDEVERSION "${KDEVERSION}") +ENDIF(KDE3_KDECONFIG_EXECUTABLE) +SET(KDE_MIN_VERSION "3.5.0") +MACRO_ENSURE_VERSION(${KDE_MIN_VERSION} ${KDEVERSION} VERSION_OK) + +IF(VERSION_OK) + SET(ACTION_MENU "X-KDE-GetActionMenu=kded kdesvnd getActionMenu(KURL::List)") +ELSE(VERSION_OK) + SET(ACTION_MENU "Actions=Update;Commit;Add;Delete;Blame;Log;Diff;Checkout;Export;Info;Addnew;Switch;Revert;Rename;Tree") +ENDIF(VERSION_OK) + +CONFIGURE_FILE(kdesvn_subversion.desktop.in + ${CMAKE_CURRENT_BINARY_DIR}/kdesvn_subversion.desktop @ONLY) + +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdesvn_subversion.desktop + DESTINATION ${DATA_INSTALL_DIR}/konqueror/servicemenus) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/kdesvnd.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kded) diff --git a/src/kdesvnd/kdesvn_subversion.desktop.in b/src/kdesvnd/kdesvn_subversion.desktop.in new file mode 100644 index 0000000..4897342 --- /dev/null +++ b/src/kdesvnd/kdesvn_subversion.desktop.in @@ -0,0 +1,368 @@ +[Desktop Entry] +Encoding=UTF-8 +ServiceTypes=inode/directory,all/allfiles +X-KDE-Submenu=Subversion (kdesvn) + +@ACTION_MENU@ + +[Desktop Action Log] +Name=Subversion log (last 100) +Name[es]=Mostrar registros (últimos 100) +Icon=kdesvnlog +Exec=kdesvn exec -r HEAD:1 -l 100 log %U +Comment=Displays the subversion log +Comment[es]=Muestra los registros de Subversion + +[Desktop Action Info] +Name=Detailed subversion info +Name[es]=Información detallada +Icon=kdesvninfo +Exec=kdesvn exec info %U + +[Desktop Action Add] +Name=Add to Repository +Name[bg]=Добавяне в хранилището +Name[da]=Tilføj til lager +Name[et]=Hoidlasse lisamine +Name[sr]=Додај у складиште +Name[sr@Latn]=Dodaj u skladište +Name[sv]=Lägg till i arkiv +Name[tr]=Depoya Ekle +Name[es]=Añadir al Repositorio +Icon=kdesvnadd +Exec=kdesvn exec add %U + +[Desktop Action Addnew] +Name=Check for unversioned items +Name[es]=Mostrar elementos no versionados +Icon=kdesvnaddrecursive +Exec=kdesvn exec addnew %U + +[Desktop Action Delete] +Name=Delete From Repository +Name[bg]=Изтриване от хранилището +Name[da]=Slet fra lager +Name[et]=Hoidlast kustutamine +Name[sr]=Обриши из складишта +Name[sr@Latn]=Obriši iz skladišta +Name[sv]=Ta bort från arkiv +Name[tr]=Depodan Sil +Name[es]=Eliminar del Repositorio +Icon=kdesvndelete +Exec=kdesvn exec rm %U + +[Desktop Action Revert] +Name=Revert Local Changes +Name[bg]=Игнориране на локалните промени +Name[da]=Vend lokale ændringer om +Name[et]=Kohalike muudatuste tühistamine +Name[sr]=Одбаци локалне измене +Name[sr@Latn]=Odbaci lokalne izmene +Name[sv]=Återställ lokal ändring +Name[tr]=Yerel Değişiklikleri Ters Çevir +Name[es]=Deshacer cambios locales +Icon=undo +Exec=kdesvn exec revert %U +Comment=Remove any changes made locally. Warning - this cannot be undone. +Comment[bg]=Премахване на локалните промени, които са направени. Забележете, че данните ще се загубят безвъзвратно. +Comment[da]=Fjern alle ændringer der er lavet lokalt. Advarsel - dette kan ikke fortrydes. +Comment[et]=Eemaldab kõik kohalikud muudatused. Hoiatus: seda ei saa tagasi võtta. +Comment[sr]=Уклони све локално направљене измене. Упозорење: ово се не може опозвати. +Comment[sr@Latn]=Ukloni sve lokalno napravljene izmene. Upozorenje: ovo se ne može opozvati. +Comment[sv]=Tar bort alla ändringar som gjorts lokalt. Varning: detta kan inte ångras. +Comment[tr]=Yerel olarak yapılan değişiklikleri kaldır. Dikkat - bu işlem geri alınamaz. +Comment[es]=Deshace cualquier cambio realizado localmente. Aviso - no se puede invertir el proceso. + +[Desktop Action Rename] +Name=Rename... +Name[bg]=Преименуване... +Name[br]=Adenvel ... +Name[cy]=Ail-enwi... +Name[da]=Omdøb... +Name[et]=Ümbernimetamine... +Name[ga]=Athainmnigh... +Name[sr]=Преименуј... +Name[sr@Latn]=Preimenuj... +Name[sv]=Byt namn... +Name[tr]=Yeniden Adlandır... +Name[es]=Renombrar... +Icon=pencil +Exec=kdesvn exec mv %U +Comment=Rename a file locally and in the repository. Use this rather than adding and deleting to rename a file. +Comment[bg]=Преименуване на файл локално и в хранилището. За предпочитане е да използвате този метод, вместо изтриване и добавяне. +Comment[da]=Omdøb en fil lokalt og i lageret. Brug dette i stedet for at tilføje og slette fro at omdøbe en fil. +Comment[et]=Faili ümbernimetamine nii kohalikult kui hoidlas. See on eelistatud viis faili ümbernimetamisel lisamise ja kustutamise asemel. +Comment[sr]=Преименуј фајл локално и у складишту. Користите ово уместо трика са додавањем и брисањем фајла. +Comment[sr@Latn]=Preimenuj fajl lokalno i u skladištu. Koristite ovo umesto trika sa dodavanjem i brisanjem fajla. +Comment[sv]=Byt namn på en fil lokalt och i arkivet. Använd detta istället för att lägga till och ta bort för att byta namn på en fil. +Comment[es]=Renombra un fichero localmente y en el repositorio. Utilizar ésto en lugar de añadir y borrar el fichero. + +[Desktop Action Import] +Name=Import Repository +Name[bg]=Импорт на директория +Name[da]=Importér lager +Name[et]=Hoidla import +Name[sr]=Увези складиште +Name[sr@Latn]=Uvezi skladište +Name[sv]=Importera arkiv +Name[tr]=Depoyu İçe Aktar +Name[es]=Importar Repositorio +Icon=svn_import +Exec=kio_svn_helper -i %U +Comment=Put folder into an existing repository to put it under revision control. +Comment[bg]=Импорт на директория в съществуващо хранилище. +Comment[da]=Put mappe ind i et eksisterende lager for at få den ind under revisionskontrol. +Comment[et]=Kataloogi lisamine olemasolevasse versioonikontrolli süsteemi hoidlasse. +Comment[sr]=Стави фасциклу у постојеће складиште, ради стављања под контролу ревизија. +Comment[sr@Latn]=Stavi fasciklu u postojeće skladište, radi stavljanja pod kontrolu revizija. +Comment[sv]=Lägg till katalog i ett befintligt arkiv för att få den under versionskontroll +Comment[tr]=Dizini başka bie alt düzeltme controlünde var olan bir depo içine koy. +Comment[es]=Poner la carpeta en un repositorio existente para tenerla bajo control de versiones. + +[Desktop Action Checkout] +Name=Checkout From Repository... +Name[bg]=Изтегляне от хранилището... +Name[da]=Tjek ud fra lager... +Name[et]=Hoidla väljavõte... +Name[sr]=Довуци из складишта... +Name[sr@Latn]=Dovuci iz skladišta... +Name[sv]=Checka ut från ett arkiv... +Name[tr]=Depodan Kontrol Et... +Name[es]=Obtener del Repositorio... +Icon=kdesvncheckout +Exec=kdesvn exec checkout %U +Comment=Checkout out files from an existing repository into this folder. +Comment[bg]=Изтегляне на файлове от хранилището в текущата директория. +Comment[da]=Tjek filer ud fra et eksisterende lager til denne mappe. +Comment[et]=Olemasoleva hoidla failide väljavõte sellesse kataloogi. +Comment[sr]=Довуци фајлове из постојећег складишта у ову фасциклу. +Comment[sr@Latn]=Dovuci fajlove iz postojećeg skladišta u ovu fasciklu. +Comment[sv]=Checka ut filer från ett befintligt arkiv till katalogen. +Comment[tr]=Bu dizinde var olan bir depodan hatalı dosyaları kontrol et. +Comment[es]=Extrae ficheros de un repositorio existente hacia esta carpeta. + +[Desktop Action Switch] +Name=Switch... +Name[bg]=Превключване... +Name[et]=Lülitumine... +Name[sr]=Пребаци... +Name[sr@Latn]=Prebaci... +Name[sv]=Byt... +Name[tr]=Değiştir... +Name[es]=Relocalizar... +Icon=kdesvnswitch +Comment=Switch given working copy to another branch +Comment[bg]=Превключване на работното копие към друго разклонение. +Comment[da]=Skift given arbejdskopi til en anden gren. +Comment[et]=Antud töökoopia lülitamine teise harru +Comment[sr]=Пребаци дату радну копију на другу грану +Comment[sr@Latn]=Prebaci datu radnu kopiju na drugu granu +Comment[sv]=Byt angiven arbetskopia till en annan gren +Comment[tr]=Çalışan belirli bir kopyayı başka bölüme değiştir +Comment[es]=Relocaliza la copia de trabajo hacia otra rama +Exec=kdesvn exec switch %U + +[Desktop Action Merge] +Name=Merge... +Name[bg]=Смесване... +Name[da]=Indflet... +Name[et]=Ühendamine... +Name[sr]=Стопи... +Name[sr@Latn]=Stopi... +Name[sv]=Sammanfoga... +Name[tr]=Birleştir... +Name[es]=Fusionar... +Icon=svn_merge +Comment=Merge changes between this and another branch +Comment[bg]=Смесване на промените от това разклонение с друго разклонение. +Comment[da]=Indflet ændringer mellem denne og en anden gren +Comment[et]=Selle ja teise haru muudatuste ühendamine +Comment[sr]=Стопи измене између ове и друге гране +Comment[sr@Latn]=Stopi izmene između ove i druge grane +Comment[sv]=Sammanfoga ändringar mellan den här och en annan gren +Comment[tr]=Bu ve başka bölüm arasındaki değişiklikleri birleştir +Comment[es]=Fusionar cambios entre esta rama y otra +Exec=kio_svn_helper -m %U + +[Desktop Action Blame] +Name=Blame... +Name[bg]=Информация... +Name[et]=Autorsus... +Name[pa]=ਬਲਾਮੀ... +Name[sr]=Окриви... +Name[sr@Latn]=Okrivi... +Name[sv]=Klandra... +Name[es]=Ver anotado... +Icon=kdesvnblame +Comment=See who wrote each line of the file and in what revision +Comment[bg]=Информация за файла. +Comment[da]=Se hvem der skrev hver linje i filen og i hvilken revision +Comment[et]=Vaatamine, kes ja millises versioonis mingi faili rea kirjutas +Comment[sr]=Прикажи за сваку линију фајла ко ју је написао и у којој ревизији +Comment[sr@Latn]=Prikaži za svaku liniju fajla ko ju je napisao i u kojoj reviziji +Comment[sv]=Se vem som skrev varje rad i filen och för vilken version +Comment[es]=Ver quién escribió cada línea del fichero y en qué revisión +Exec=kdesvn exec blame %U + +[Desktop Action CreatePatch] +Name=Create Patch... +Name[bg]=Създаване на кръпка... +Name[da]=Lav rettelse... +Name[et]=Paiga loomine... +Name[pa]=ਪੈਂਚ ਬਣਾਓ... +Name[sr]=Направи закрпу... +Name[sr@Latn]=Napravi zakrpu... +Name[sv]=Skapa programfix... +Name[tr]=Yama Oluştur... +Name[es]=Crear Parche... +Exec=kio_svn_helper -p %U + +[Desktop Action Export] +Name=Export... +Name[bg]=Експорт... +Name[br]=Ezporzh ... +Name[cy]=Allforio... +Name[da]=Eksportér... +Name[et]=Eksport... +Name[ga]=Easpórtáil... +Name[sr]=Извези... +Name[sr@Latn]=Izvezi... +Name[sv]=Exportera... +Name[tr]=Dışa Aktar... +Name[es]=Exportar... +Icon=kdesvnexport +Exec=kdesvn exec export %U +Comment=Checkout out an unversioned copy of a tree from a repository +Comment[bg]=Изтегляне на копие на дървото от хранилището. +Comment[da]=Tjek en kopi uden version ud af et træ fra et lager +Comment[et]=Hoidla failipuu versioonita koopia väljavõte +Comment[sr]=Довуци неверзирану копију стабла из складишта +Comment[sr@Latn]=Dovuci neverziranu kopiju stabla iz skladišta +Comment[sv]=Checka ut en kopia utan versionskontroll från ett arkiv +Comment[tr]=Depodaki bir ağaçtan kusurlu bir versionsuz kopyayı kontrol et +Comment[es]=Obtener una copia no versionada de un árbol de un repositorio + +[Desktop Action Diff] +Name=Diff (local) +Name[bg]=Разлика (локално) +Name[da]=Diff (lokal) +Name[et]=Võrdlemine (kohalik) +Name[ga]=Diff (logánta) +Name[sr]=Разликуј (локално) +Name[sr@Latn]=Razlikuj (lokalno) +Name[sv]=Jämför (lokalt) +Name[tr]=Diff (yerel) +Name[es]=Ver diferencias (locales) +Icon=kdesvndiff +Exec=kdesvn exec diff %U +Comment=Show local changes since last update +Comment[bg]=Показване на локалните промени след последното обновяване. +Comment[da]=Vis lokale ændringer siden sidste opdatering +Comment[et]=Kohalike muudatuste näitamine pärast viimast uuendamist +Comment[sr]=Прикажи локалне измене од последњег ажурирања +Comment[sr@Latn]=Prikaži lokalne izmene od poslednjeg ažuriranja +Comment[sv]=Visa lokala ändringar sedan senaste uppdateringen +Comment[tr]=Son güncellemeden sonraki yerel değişiklikleri göster +Comment[es]=Mostrar cambios locales desde la última actualización + +[Desktop Action Update] +Name=KDESvn Update +Name[bg]=Обновяване SVN +Name[da]=SVN Opdatér +Name[et]=SVN uuendamine +Name[sr]=SVN ажурирање +Name[sr@Latn]=SVN ažuriranje +Name[sv]=SVN-uppdatera +Name[tr]=SVN Güncelleme +Name[es]=(SVN) Actualizar +Icon=kdesvnupdate +Exec=kdesvn exec update %U + +[Desktop Action Commit] +Name=KDESvn Commit +Name[bg]=Предаване SVN +Name[et]=SVN sissekanne +Name[sr]=SVN предаја +Name[sr@Latn]=SVN predaja +Name[sv]=SVN-arkivera +Name[tr]=SVN Teslim Etme +Name[es]=(SVN) Confirmar +Icon=kdesvncommit +Exec=kdesvn exec commit %U + +[Desktop Action Checkout] +Name=Checkout From Repository... +Name[bg]=Изтегляне от хранилището... +Name[da]=Tjek ud fra lager... +Name[et]=Hoidla väljavõte... +Name[sr]=Довуци из складишта... +Name[sr@Latn]=Dovuci iz skladišta... +Name[sv]=Checka ut från ett arkiv... +Name[tr]=Depodan Kontrol Et... +Name[es]=(SVN) Obtener del Repositorio... +Icon=kdesvncheckout +Exec=kdesvn exec checkout %U +Comment=Checkout out files from an existing repository into this folder. +Comment[bg]=Изтегляне на файлове от хранилището в текущата директория. +Comment[da]=Tjek filer ud fra et eksisterende lager til denne mappe. +Comment[et]=Olemasoleva hoidla failide väljavõte sellesse kataloogi. +Comment[sr]=Довуци фајлове из постојећег складишта у ову фасциклу. +Comment[sr@Latn]=Dovuci fajlove iz postojećeg skladišta u ovu fasciklu. +Comment[sv]=Checka ut filer från ett befintligt arkiv till katalogen. +Comment[tr]=Bu dizinde var olan bir depodan hatalı dosyaları kontrol et. +Comment[es]=Extraer ficheros de un repositorio existente hacia esta carpeta. + +[Desktop Action Export] +Name=Export ... +Name[bg]=Експорт... +Name[br]=Ezporzh ... +Name[cy]=Allforio... +Name[da]=Eksportér... +Name[et]=Eksport... +Name[ga]=Easpórtáil... +Name[sr]=Извези... +Name[sr@Latn]=Izvezi... +Name[sv]=Exportera... +Name[tr]=Dışa Aktar... +Name[es]=(SVN) Exportar... +Icon=kdesvnexport +Exec=kdesvn exec export %U +Comment=Checkout out an unversioned copy of a tree from a repository +Comment[bg]=Изтегляне на копие на дървото от хранилището. +Comment[da]=Tjek en kopi uden version ud af et træ fra et lager +Comment[et]=Hoidla failipuu versioonita koopia väljavõte +Comment[sr]=Довуци неверзирану копију стабла из складишта +Comment[sr@Latn]=Dovuci neverziranu kopiju stabla iz skladišta +Comment[sv]=Checka ut en kopia utan versionskontroll från ett arkiv +Comment[tr]=Depodaki bir ağaçtan kusurlu bir versionsuz kopyayı kontrol et +Comment[es]=Obtener una copia no versionada del árbol de un repositorio + +[Desktop Action Checkoutto] +Name=Checkout from a repository... +Name[de]=Checkout einer Repository +Name[es]=Obtener de Subversion... +Icon=kdesvncheckout +Exec=kdesvn exec checkoutto %U +Comment=Checkout out files from an existing repository into this folder. +Comment[de]=Erzeuge eine Arbeitskopie von einer Repository +Comment[es]=Extraer ficheros de un repositorio existente hacia esta carpeta. + +[Desktop Action Exportto] +Name=Export from a subversion repository... +Name[de]=Exportiere von einer Subversion Repository... +Name[es]=Exportar de Subversion... +Icon=kdesvnexport +Exec=kdesvn exec exportto %U +Comment=Checkout out an unversioned copy of a tree from a repository +Comment[de]=Hole eine unversionierte Kopie eines Baums von einer Repository +Comment[es]=Obtener una copia no versionada del árbol de un repositorio + +[Desktop Action Tree] +Name=Display revision tree +Name[de]=Zeige Revisionsbaum +Name[es]=Mostrar árbol de revisiones +Icon=kdesvnlog +Exec=kdesvn exec tree %U +Comment[de]=Zeige den kompletten Revisionsbaum +Comment=Show complete revision tree +Comment[es]=Muestra el árbol de revisiones completo diff --git a/src/kdesvnd/kdesvnd.desktop b/src/kdesvnd/kdesvnd.desktop new file mode 100644 index 0000000..eb9c91c --- /dev/null +++ b/src/kdesvnd/kdesvnd.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Service +Name=kdesvnd subversion module +Name[es]=módulo para subversion kdesvnd +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=kdesvnd +X-KDE-FactoryName=kdesvnd +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=true + diff --git a/src/kdesvnd/kdesvnd_dcop.cpp b/src/kdesvnd/kdesvnd_dcop.cpp new file mode 100644 index 0000000..580fa92 --- /dev/null +++ b/src/kdesvnd/kdesvnd_dcop.cpp @@ -0,0 +1,461 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * rajko.albrecht@tecways.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "kdesvn-config.h" +#include "kdesvnd_dcop.h" +#include "src/ksvnwidgets/authdialogimpl.h" +#include "src/ksvnwidgets/ssltrustprompt_impl.h" +#include "src/ksvnwidgets/logmsg_impl.h" +#include "src/settings/kdesvnsettings.h" +#include "src/ksvnwidgets/pwstorage.h" +#include "src/svnqt/client.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/status.hpp" +#include "src/svnqt/context_listener.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/ktranslateurl.h" + +#include <kdebug.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kglobal.h> +#include <kfiledialog.h> +#include <kpassdlg.h> + +#include <qdir.h> + +extern "C" { + KDESVN_EXPORT KDEDModule *create_kdesvnd(const QCString &name) + { + return new kdesvnd_dcop(name); + } +} + +class IListener:public svn::ContextListener +{ + friend class kdesvnd_dcop; + + kdesvnd_dcop*m_back; +public: + IListener(kdesvnd_dcop*p); + virtual ~IListener(); + /* context-listener methods */ + virtual bool contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave); + virtual bool contextGetSavedLogin (const QString & realm,QString & username,QString & password); + virtual bool contextGetCachedLogin (const QString & realm,QString & username,QString & password); + + virtual void contextNotify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision); + virtual void contextNotify (const svn_wc_notify_t *action); + + virtual bool contextCancel(); + virtual bool contextGetLogMessage (QString & msg,const svn::CommitItemList&); + virtual svn::ContextListener::SslServerTrustAnswer + contextSslServerTrustPrompt (const SslServerTrustData & data, + apr_uint32_t & acceptedFailures); + virtual bool contextSslClientCertPrompt (QString & certFile); + virtual bool contextLoadSslClientCertPw(QString&password,const QString&realm); + virtual bool contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maySave); + virtual void contextProgress(long long int current, long long int max); + + /* context listener virtuals end */ + +protected: + svn::Client* m_Svnclient; + svn::ContextP m_CurrentContext; +}; + +IListener::IListener(kdesvnd_dcop*p) + :svn::ContextListener() +{ + m_Svnclient = svn::Client::getobject(0,0); + m_back=p; + m_CurrentContext = new svn::Context(); + m_CurrentContext->setListener(this); + m_Svnclient->setContext(m_CurrentContext); +} + +IListener::~IListener() +{ +} + +kdesvnd_dcop::kdesvnd_dcop(const QCString&name) : KDEDModule(name) +{ + KGlobal::locale()->insertCatalogue("kdesvn"); + m_Listener=new IListener(this); +} + +kdesvnd_dcop::~kdesvnd_dcop() +{ + delete m_Listener; +} + +QStringList kdesvnd_dcop::getActionMenu (const KURL::List list) +{ + QStringList result; + Kdesvnsettings::self()->readConfig(); + if (Kdesvnsettings::no_konqueror_contextmenu()||list.count()==0) { + return result; + } + QString base; + + + bool parentIsWc = false; + bool itemIsWc = isWorkingCopy(list[0],base); + bool itemIsRepository = false; + + QString _par = list[0].directory(true,true); + parentIsWc = isWorkingCopy(_par,base); + + if (!parentIsWc && !itemIsWc) { + itemIsRepository = isRepository(list[0]); + } + + if (!itemIsWc) { + if (itemIsRepository) { + result << "Export" + << "Checkout"; + } else { + result << "Exportto" + << "Checkoutto"; + } + } else { + result << "Update" + << "Commit"; + } + + if (!parentIsWc && !itemIsWc) { + if (itemIsRepository) { + result << "Log" + << "Info"; + if (isRepository(list[0].upURL())) { + result << "Blame" + << "Rename"; + } + result << "Tree"; + } + return result; + } + + if (!itemIsWc) { + result << "Add"; + return result; + } + + result << "Log" + << "Tree" + << "Info" + << "Diff" + << "Rename" + << "Revert"; + + KURL url = helpers::KTranslateUrl::translateSystemUrl(list[0]); + + QFileInfo f(url.path()); + if (f.isFile()) { + result << "Blame"; + } + + if (f.isDir()) { + result << "Addnew"; + result << "Switch"; + } + + return result; +} + +QStringList kdesvnd_dcop::getSingleActionMenu(QCString what) +{ + KURL::List l; l.append(KURL(what)); + return getActionMenu(l); +} + +QStringList kdesvnd_dcop::get_login(QString realm,QString user) +{ + AuthDialogImpl auth(realm,user); + QStringList res; + if (auth.exec()==QDialog::Accepted) { + res.append(auth.Username()); + res.append(auth.Password()); + if (auth.maySave()) { + res.append("true"); + } else { + res.append("false"); + } + } + return res; +} + +int kdesvnd_dcop::get_sslaccept(QString hostname,QString fingerprint,QString validFrom,QString validUntil,QString issuerDName,QString realm) +{ + bool ok,saveit; + if (!SslTrustPrompt_impl::sslTrust( + hostname, + fingerprint, + validFrom, + validUntil, + issuerDName, + realm, + QStringList(), + &ok,&saveit)) { + return -1; + } + if (!saveit) { + return 0; + } + return 1; +} + +QStringList kdesvnd_dcop::get_sslclientcertpw(QString realm) +{ + QStringList resList; + QCString npass; + int keep = 1; + int res = KPasswordDialog::getPassword(npass,i18n("Enter password for realm %1").arg(realm),&keep); + if (res!=KPasswordDialog::Accepted) { + return resList; + } + resList.append(QString(npass)); + if (keep) { + resList.append("true"); + } else { + resList.append("false"); + } + return resList; +} + +QString kdesvnd_dcop::get_sslclientcertfile() +{ + QString afile = KFileDialog::getOpenFileName(QString::null, + QString::null, + 0, + i18n("Open a file with a #PKCS12 certificate")); + return afile; +} + +QStringList kdesvnd_dcop::get_logmsg() +{ + QStringList res; + bool ok; + QString logMessage = Logmsg_impl::getLogmessage(&ok,0,0,0,"logmsg_impl"); + if (!ok) { + return res; + } + res.append(logMessage); + return res; +} + +QStringList kdesvnd_dcop::get_logmsg(QMap<QString,QString> list) +{ + QStringList res; + bool ok; + QString logMessage = Logmsg_impl::getLogmessage(list,&ok,0,0,0,"logmsg_impl"); + if (!ok) { + return res; + } + res.append(logMessage); + return res; +} + +QString kdesvnd_dcop::cleanUrl(const KURL&url) +{ + QString cleanpath = url.path(); + while (cleanpath.endsWith("/")) { + cleanpath.truncate(cleanpath.length()-1); + } + return cleanpath; +} + +/* just simple name check of course - no network acess! */ +bool kdesvnd_dcop::isRepository(const KURL&url) +{ + kdDebug()<<"kdesvnd_dcop::isRepository Url zum repo check: "<<url<<endl; + QString proto = svn::Url::transformProtokoll(url.protocol()); + kdDebug()<<"kdesvnd_dcop::isRepository Protokoll: " << proto << endl; + if (proto=="file") { + // local access - may a repository + svn::Revision where = svn::Revision::HEAD; + svn::StatusEntries dlist; + try { + m_Listener->m_Svnclient->status("file://"+cleanUrl(url),svn::DepthEmpty,false,false,false,where); + } catch (const svn::ClientException&e) { + kdDebug()<< e.msg()<<endl; + return false; + } + return true; + } else { + return svn::Url::isValid(proto); + } +} + +bool kdesvnd_dcop::isWorkingCopy(const KURL&_url,QString&base) +{ + base = ""; + KURL url = _url; + url = helpers::KTranslateUrl::translateSystemUrl(url); + + if (url.isEmpty()||!url.isLocalFile()||url.protocol()!="file") return false; + svn::Revision peg(svn_opt_revision_unspecified); + svn::Revision rev(svn_opt_revision_unspecified); + svn::InfoEntries e; + try { + e = m_Listener->m_Svnclient->info(cleanUrl(url),svn::DepthEmpty,rev,peg); + } catch (const svn::ClientException&e) { + kdDebug()<< e.msg()<<endl; + return false; + } + base=e[0].url(); + return true; +} + +bool IListener::contextGetSavedLogin (const QString & realm,QString & username,QString & password) +{ + PwStorage::self()->getLogin(realm,username,password); + return true; +} + +bool IListener::contextGetCachedLogin (const QString & realm,QString & username,QString & password) +{ + return true; +} + +bool IListener::contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave) +{ + maySave=false; + QStringList res = m_back->get_login(realm,username); + if (res.count()!=3) { + return false; + } + username = res[0]; + password = res[1]; + maySave = (res[2]=="true"); + if (maySave && Kdesvnsettings::passwords_in_wallet() ) { + PwStorage::self()->setLogin(realm,username,password); + maySave=false; + } + return true; +} + +void IListener::contextNotify(const char * /*path*/, + svn_wc_notify_action_t /*action*/, + svn_node_kind_t /*kind*/, + const char */*mime_type*/, + svn_wc_notify_state_t /*content_state*/, + svn_wc_notify_state_t /*prop_state*/, + svn_revnum_t /*revision*/) +{ +} + +void IListener::contextNotify(const svn_wc_notify_t * /*action*/) +{ +} + +bool IListener::contextCancel() +{ + return false; +} + +bool IListener::contextGetLogMessage (QString & msg,const svn::CommitItemList&) +{ + QStringList res = m_back->get_logmsg(); + if (res.count()==0) { + return false; + } + msg = res[1]; + return true; +} + +svn::ContextListener::SslServerTrustAnswer IListener::contextSslServerTrustPrompt (const SslServerTrustData & data, + apr_uint32_t & /*acceptedFailures*/) +{ + int res = m_back->get_sslaccept(data.hostname, + data.fingerprint, + data.validFrom, + data.validUntil, + data.issuerDName, + data.realm); + switch (res) { + case -1: + return DONT_ACCEPT; + break; + case 1: + return ACCEPT_PERMANENTLY; + break; + default: + case 0: + return ACCEPT_TEMPORARILY; + break; + } + /* avoid compiler warnings */ + return ACCEPT_TEMPORARILY; +} + +bool IListener::contextSslClientCertPrompt (QString & certFile) +{ + certFile = m_back->get_sslclientcertfile(); + if (certFile.isEmpty()) { + return false; + } + return true; +} + +bool IListener::contextLoadSslClientCertPw(QString&password,const QString&realm) +{ + return PwStorage::self()->getCertPw(realm,password); +} + +bool IListener::contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maySave) +{ + maySave=false; + if (PwStorage::self()->getCertPw(realm,password)) { + return true; + } + QStringList res = m_back->get_sslclientcertpw(realm); + if (res.size()!=2) { + return false; + } + password=res[0]; + maySave=res[1]==QString("true"); + + if (maySave && Kdesvnsettings::passwords_in_wallet() ) { + PwStorage::self()->setCertPw(realm,password); + maySave=false; + } + + return true; +} + +void IListener::contextProgress(long long int, long long int) +{ +} diff --git a/src/kdesvnd/kdesvnd_dcop.h b/src/kdesvnd/kdesvnd_dcop.h new file mode 100644 index 0000000..61b8f83 --- /dev/null +++ b/src/kdesvnd/kdesvnd_dcop.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * rajko.albrecht@tecways.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef _kdesvnd_dcop_H +#define _kdesvnd_dcop_H + +#include <qstringlist.h> +#include <qstring.h> +#include <kurl.h> +#include <dcopobject.h> +#include <kdedmodule.h> + +class IListener; + +class kdesvnd_dcop : public KDEDModule +{ + Q_OBJECT + K_DCOP + +private: + +public: + kdesvnd_dcop(const QCString&); + virtual ~kdesvnd_dcop(); + +protected: + bool isWorkingCopy(const KURL&url,QString&base); + bool isRepository(const KURL&url); + static QString cleanUrl(const KURL&url); + IListener*m_Listener; + +k_dcop: + //! get a subversion login + /*! + * \param realm the realm + * \param user default username + * \return a stringlist containing username-password-saveit as "true" or "false" or empty list if cancel hit. + */ + QStringList get_login(QString,QString); + + // return: -1 dont accept 0 accept temporary 1 accept always + // hostname, fingerprint, validFrom, validUntil, issuerDName, realm, + int get_sslaccept(QString, QString, QString, QString, QString, QString); + + // returns cert file or empty string + QString get_sslclientcertfile(); + // return a logmessage at pos 0, null-size list if cancel hit + QStringList get_logmsg(); + // return a logmessage at pos 0, null-size list if cancel hit, parameter is path -> action for display + QStringList get_logmsg(QMap<QString,QString>); + // return pw at pos 0, maysafe at pos 1, null-size if cancel hit. + QStringList get_sslclientcertpw(QString); + QStringList getActionMenu(KURL::List); + QStringList getSingleActionMenu(QCString); +}; +#endif diff --git a/src/kdesvnd/main.cpp b/src/kdesvnd/main.cpp new file mode 100644 index 0000000..671b50a --- /dev/null +++ b/src/kdesvnd/main.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2005 by Rajko Albrecht * + * rajko.albrecht@tecways.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include <kuniqueapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <kaboutdata.h> +#include <klocale.h> +#include <dcopclient.h> +#include "kdesvnd_dcop.h" + +static const char description[] = + I18N_NOOP("Kdesvn DCOP service"); + +static const char version[] = "0.1"; + +static KCmdLineOptions options[] = +{ + KCmdLineLastOption +}; + +int main (int argc, char *argv[]) +{ + KLocale::setMainCatalogue("kdesvn"); + KAboutData aboutdata("kdesvnd", I18N_NOOP("KDE"), + version, description, + KAboutData::License_GPL, "(C) %{YEAR}, Rajko Albrecht"); + aboutdata.addAuthor("Rajko Albrecht",I18N_NOOP("Developer"),"rajko.albrecht@tecways.com"); + + KCmdLineArgs::init( argc, argv, &aboutdata ); + KCmdLineArgs::addCmdLineOptions( options ); + KUniqueApplication::addCmdLineOptions(); + + if (!KUniqueApplication::start()) + { + kdDebug() << "kdesvnd is already running!" << endl; + return (0); + } + + KUniqueApplication app; + kdDebug() << "starting kdesvnd_dcop " << endl; + // This app is started automatically, no need for session management + app.disableSessionManagement(); + kdesvnd_dcop *service = new kdesvnd_dcop; + kdDebug() << "starting kdesvnd_dcop " << endl; + return app.exec(); + +} diff --git a/src/kdesvnui.rc b/src/kdesvnui.rc new file mode 100644 index 0000000..23fd78e --- /dev/null +++ b/src/kdesvnui.rc @@ -0,0 +1,60 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui version="6" name="kdesvn" > + <MenuBar> + <Menu noMerge="1" name="file"><text>&File</text> + <Action name="file_open"/> + <Action name="file_open_recent"/> + <Action name="file_new"/> + <Separator/> + <Menu name="subversion_admin" noMerge="1"> + <text>Subversion Admin</text> + <Action name="subversion_create_repo"/> + <Action name="subversion_dump_repo"/> + <Action name="subversion_hotcopy_repo"/> + <Action name="subversion_load_repo"/> + <Merge/> + </Menu> + <Separator/> + <Merge/> + <Action name="file_close"/> + <Separator/> + <Action name="file_quit"/> + </Menu> + <Action name="bookmarks" /> + <Menu noMerge="1" name="subversion_main" > + <text>Subversion</text> + <Merge/> + <Action name="kdesvn_ssh_add"/> + </Menu> + <Menu noMerge="1" name="settings"> + <text>&Settings</text> + <Action name="options_show_toolbar"/> + <Action name="options_show_statusbar"/> + <Separator /> + <Action name="toggle_load_last_url" /> + <Action name="show_merge" /> + <Separator /> + <Action name="options_configure_keybinding"/> + <Action name="options_configure_toolbars"/> + <Merge name="configure_merge"/> + <Separator/> + <Merge/> + </Menu> + <Menu noMerge="0" name="help"> + <text>&Help</text> + <Merge/> + <Action name="help_about_kdesvnpart"/> + </Menu> + </MenuBar> +<ToolBar name="subversionToolBar" noMerge="1"> +<text>Subversion toolbar</text> +<Merge/> +</ToolBar> + <ToolBar noMerge="1" name="mainToolBar" > + <text>Main Toolbar</text> + <Action name="file_open" /> + <Merge/> + <Action name="file_close"/> + <Action name="help" /> + </ToolBar> +</kpartgui> diff --git a/src/kdesvnview.cpp b/src/kdesvnview.cpp new file mode 100644 index 0000000..2312730 --- /dev/null +++ b/src/kdesvnview.cpp @@ -0,0 +1,485 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "kdesvnview.h" +#include "svnfrontend/kdesvnfilelist.h" +#include "svnfrontend/createrepo_impl.h" +#include "svnfrontend/dumprepo_impl.h" +#include "svnfrontend/hotcopydlg_impl.h" +#include "svnfrontend/loaddmpdlg_impl.h" +#include "svnfrontend/stopdlg.h" +#include "svnfrontend/fronthelpers/propertylist.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/url.hpp" +#include "src/svnqt/repository.hpp" +#include "src/svnqt/version_check.hpp" +#include "src/svnqt/svnqttypes.hpp" + +#include <qpainter.h> +#include <qlayout.h> +#include <qfileinfo.h> +#include <qheader.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qsplitter.h> +#include <qlayout.h> +#include <qvbox.h> + +#include <kurl.h> +#include <ktrader.h> +#include <kapplication.h> +#include <klibloader.h> +#include <kmessagebox.h> +#include <krun.h> +#include <klocale.h> +#include <ktextbrowser.h> +#include <kdebug.h> +#include <kactioncollection.h> +#include <kshortcut.h> +#include <kdialog.h> +#include <kdialogbase.h> +#include <kprogress.h> + +kdesvnView::kdesvnView(KActionCollection*aCollection,QWidget *parent,const char*name,bool full) + : QWidget(parent,name),svn::repository::RepositoryListener(),m_Collection(aCollection), + m_currentURL("") +{ + Q_UNUSED(full); + setupActions(); + m_CacheProgressBar=0; + + m_topLayout = new QVBoxLayout(this); + + m_Splitter = new QSplitter( this, "m_Splitter" ); + m_Splitter->setOrientation( QSplitter::Vertical ); + + m_flist=new kdesvnfilelist(m_Collection,m_Splitter); + + m_infoSplitter = new QSplitter(m_Splitter); + m_infoSplitter->setOrientation( QSplitter::Horizontal ); + m_infoSplitter->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 0, 1, m_infoSplitter->sizePolicy().hasHeightForWidth() ) ); + m_LogWindow=new KTextBrowser(m_infoSplitter); + Propertylist*pl = new Propertylist(m_infoSplitter); + pl->setCommitchanges(true); + pl->addCallback(m_flist); + connect(m_flist,SIGNAL(sigProplist(const svn::PathPropertiesMapListPtr&,bool,const QString&)), + pl,SLOT(displayList(const svn::PathPropertiesMapListPtr&,bool,const QString&))); + + m_flist->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 0, 1, m_flist->sizePolicy().hasHeightForWidth() ) ); + + m_topLayout->addWidget(m_Splitter); + connect(m_flist,SIGNAL(sigLogMessage(const QString&)),this,SLOT(slotAppendLog(const QString&))); + connect(m_flist,SIGNAL(changeCaption(const QString&)),this,SLOT(slotSetTitle(const QString&))); + connect(m_flist,SIGNAL(sigShowPopup(const QString&,QWidget**)),this,SLOT(slotDispPopup(const QString&,QWidget**))); + connect(m_flist,SIGNAL(sigUrlOpend(bool)),parent,SLOT(slotUrlOpened(bool))); + connect(m_flist,SIGNAL(sigSwitchUrl(const KURL&)),this,SIGNAL(sigSwitchUrl(const KURL&))); + connect(m_flist,SIGNAL(sigUrlChanged( const QString& )),this,SLOT(slotUrlChanged(const QString&))); + connect(m_flist,SIGNAL(sigCacheStatus(Q_LONG,Q_LONG)),this,SLOT(fillCacheStatus(Q_LONG,Q_LONG))); + connect(this,SIGNAL(sigMakeBaseDirs()),m_flist,SLOT(slotMkBaseDirs())); + KConfigGroup cs(Kdesvnsettings::self()->config(),"kdesvn-mainlayout"); + QString t1 = cs.readEntry("split1",QString::null); + if (!t1.isEmpty()) { + QTextStream st1(&t1,IO_ReadOnly); + st1 >> *m_Splitter; + } + if (m_infoSplitter) { + t1 = cs.readEntry("infosplit",QString::null); + if (!t1.isEmpty()) { + QTextStream st2(&t1,IO_ReadOnly); + st2 >> *m_infoSplitter; + } + } +} + +void kdesvnView::slotAppendLog(const QString& text) +{ + m_LogWindow->append(text); +} + +kdesvnView::~kdesvnView() +{ + KConfigGroup cs(Kdesvnsettings::self()->config(),"kdesvn-mainlayout"); + QString t1,t2; + QTextStream st1(&t1,IO_WriteOnly); + st1 << *m_Splitter; + cs.writeEntry("split1",t1); + + if (m_infoSplitter) { + t2=""; + QTextStream st2(&t2,IO_WriteOnly); + st2 << *m_infoSplitter; + cs.writeEntry("infosplit",t2); + } +} + +void kdesvnView::slotUrlChanged(const QString&url) +{ + m_currentURL=url; + slotSetTitle(url); + emit sigUrlChanged(url); + slotOnURL(i18n("Repository opened")); +} + +QString kdesvnView::currentURL() +{ + return m_currentURL; +} + +bool kdesvnView::openURL(QString url) +{ + return openURL(KURL(url)); +} + +bool kdesvnView::openURL(const KURL& url) +{ + /* transform of url must be done in part! otherwise we will run into different troubles! */ + m_currentURL = ""; + KURL _url; + bool open = false; + _url = url; + if (_url.isLocalFile()) { + QString query = _url.query(); + _url.setQuery(""); + QString _f = _url.path(); + QFileInfo f(_f); + if (!f.isDir()) { + m_currentURL=""; + return open; + } + if (query.length()>1) { + _url.setQuery(query); + } + } else { + if (!svn::Url::isValid(url.protocol())) { + return open; + } + } + m_LogWindow->setText(""); + slotSetTitle(url.prettyURL()); + if (m_flist->openURL(url)) { + slotOnURL(i18n("Repository opened")); + m_currentURL=url.url(); + open = true; + } else { + QString t = m_flist->lastError(); + if (t.isEmpty()) { + t = i18n("Could not open repository"); + } + slotOnURL(t); + } + return open; +} + +void kdesvnView::slotOnURL(const QString& url) +{ + emit signalChangeStatusbar(url); +} + +void kdesvnView::slotSetTitle(const QString& title) +{ + //emit signalChangeCaption(title); + emit setWindowCaption(title); +} + + +/*! + \fn kdesvnView::closeMe() + */ +void kdesvnView::closeMe() +{ + m_flist->closeMe(); + m_LogWindow->setText(""); + slotOnURL(i18n("No repository open")); +} + +void kdesvnView::slotDispPopup(const QString&item,QWidget**target) +{ + emit sigShowPopup(item,target); +} + + +/*! + \fn kdesvnView::refreshCurrentTree() + */ +void kdesvnView::refreshCurrentTree() +{ + m_flist->refreshCurrentTree(); +} + + +/*! + \fn kdesvnView::slotSettingsChanged() + */ +void kdesvnView::slotSettingsChanged() +{ + m_flist->slotSettingsChanged(); +} + +/*! + \fn kdesvnView::slotCreateRepo() + */ +void kdesvnView::slotCreateRepo() +{ + KDialogBase * dlg = new KDialogBase( + KApplication::activeModalWidget(), + "create_repository", + true, + i18n("Create new repository"), + KDialogBase::Ok|KDialogBase::Cancel); + if (!dlg) return; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + bool compatneeded = svn::Version::version_major()>1||svn::Version::version_minor()>3; + bool compat14 = svn::Version::version_major()>1||svn::Version::version_minor()>4; + Createrepo_impl*ptr = new Createrepo_impl(compatneeded,compat14,Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"create_repo_size")); + int i = dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"create_repo_size",false); + + if (i!=QDialog::Accepted) { + delete dlg; + return; + } + svn::repository::Repository*_rep = new svn::repository::Repository(this); + bool ok = true; + bool createdirs; + QString path = ptr->targetDir(); + closeMe(); + kdDebug()<<"Creating "<<path << endl; + try { + _rep->CreateOpen(path,ptr->fsType(),ptr->disableFsync(), + !ptr->keepLogs(),ptr->compat13(),ptr->compat14()); + } catch(const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Creating "<<path << " failed "<<e.msg() << endl; + ok = false; + } + kdDebug()<<"Creating "<<path << " done " << endl; + createdirs = ptr->createMain(); + delete dlg; + delete _rep; + if (!ok) { + return; + } + openURL(path); + if (createdirs) { + emit sigMakeBaseDirs(); + } +} + +void kdesvnView::slotHotcopy() +{ + KDialogBase * dlg = new KDialogBase( + KApplication::activeModalWidget(), + "hotcopy_repository", + true, + i18n("Hotcopy a repository"), + KDialogBase::Ok|KDialogBase::Cancel); + if (!dlg) return; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + HotcopyDlg_impl * ptr = new HotcopyDlg_impl(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"hotcopy_repo_size")); + int i = dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"hotcopy_repo_size",false); + + if (i!=QDialog::Accepted) { + delete dlg; + return; + } + bool cleanlogs = ptr->cleanLogs(); + QString src = ptr->srcPath(); + QString dest = ptr->destPath(); + delete dlg; + if (src.isEmpty()||dest.isEmpty()) { + return; + } + try { + svn::repository::Repository::hotcopy( src,dest,cleanlogs); + slotAppendLog(i18n("Hotcopy finished.")); + } catch(const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Hotcopy of "<< src << " failed "<<e.msg() << endl; + } +} + +void kdesvnView::slotLoaddump() +{ + KDialogBase dlg( + KApplication::activeModalWidget(), + "hotcopy_repository", + true, + i18n("Hotcopy a repository"), + KDialogBase::Ok|KDialogBase::Cancel); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + LoadDmpDlg_impl * ptr = new LoadDmpDlg_impl(Dialog1Layout); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),"loaddump_repo_size")); + int i = dlg.exec(); + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"loaddump_repo_size",false); + if (i!=QDialog::Accepted) { + return; + } + svn::repository::Repository _rep(this); + m_ReposCancel = false; + + try { + _rep.Open(ptr->repository()); + }catch (const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Open "<<ptr->repository() << " failed "<<e.msg() << endl; + return ; + } + + svn::repository::Repository::LOAD_UUID _act; + switch (ptr->uuidAction()) { + case 1: + _act = svn::repository::Repository::UUID_IGNORE_ACTION; + break; + case 2: + _act = svn::repository::Repository::UUID_FORCE_ACTION; + break; + case 0: + default: + _act = svn::repository::Repository::UUID_DEFAULT_ACTION; + break; + } + try { + StopDlg sdlg(this,this,0,"Load Dump",i18n("Loading a dump into a repository.")); + _rep.loaddump(ptr->dumpFile(),_act,ptr->parentPath(),ptr->usePre(),ptr->usePost()); + slotAppendLog(i18n("Loading dump finished.")); + }catch (const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Load dump into "<<ptr->repository() << " failed "<<e.msg() << endl; + } +} + +void kdesvnView::slotDumpRepo() +{ + KDialogBase * dlg = new KDialogBase( + KApplication::activeModalWidget(), + "dump_repository", + true, + i18n("Dump a repository"), + KDialogBase::Ok|KDialogBase::Cancel); + if (!dlg) return; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + DumpRepo_impl*ptr = new DumpRepo_impl(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"dump_repo_size")); + int i = dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"dump_repo_size",false); + + if (i!=QDialog::Accepted) { + delete dlg; + return; + } + svn::repository::Repository*_rep = new svn::repository::Repository(this); + QString re,out; + bool incr,diffs; + re = ptr->reposPath(); + out = ptr->targetFile(); + incr = ptr->incremental(); + diffs = ptr->use_deltas(); + int s = ptr->startNumber(); + int e = ptr->endNumber(); + + delete dlg; + + m_ReposCancel = false; + svn::Revision st = svn::Revision::UNDEFINED; + svn::Revision en = svn::Revision::UNDEFINED; + + if (s>-1) { + st=s; + } + if (e>-1) { + en=e; + } + + try { + _rep->Open(re); + }catch (const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Open "<<re << " failed "<<e.msg() << endl; + delete _rep; + return ; + } + + try { + StopDlg sdlg(this,this,0,"Dump",i18n("Dumping a repository")); + _rep->dump(out,st,en,incr,diffs); + slotAppendLog(i18n("Dump finished.")); + }catch (const svn::ClientException&e) { + slotAppendLog(e.msg()); + kdDebug()<<"Dump "<<out << " failed "<<e.msg() << endl; + } + delete _rep; +} + +/*! + \fn kdesvnView::setupActions() + */ +void kdesvnView::setupActions() +{ +} + +void kdesvnView::sendWarning(const QString&aMsg) +{ + slotAppendLog(aMsg); +} + +void kdesvnView::sendError(const QString&aMsg) +{ + slotAppendLog(aMsg); +} + +bool kdesvnView::isCanceld() +{ + if (!m_ReposCancel) { + emit tickProgress(); + return false; + } + return true; +} + +void kdesvnView::setCanceled(bool how) +{ + m_ReposCancel = how; +} + +void kdesvnView::fillCacheStatus(Q_LONG current,Q_LONG max) +{ + if (current>-1 && max>-1) { + kdDebug()<<"Fillcache "<<current<<" von "<<max<<endl; + if (!m_CacheProgressBar) { + kdDebug()<<"Creating progressbar"<<endl; + m_CacheProgressBar=new KProgress((int)max,this); + m_topLayout->addWidget(m_CacheProgressBar); + m_CacheProgressBar->setFormat(i18n("Inserted %v not cached log entries of %m.")); + } + if (!m_CacheProgressBar->isVisible()) { + m_CacheProgressBar->show(); + } + m_CacheProgressBar->setValue((int)current); + } else { + delete m_CacheProgressBar; + m_CacheProgressBar=0; + } +} + +#include "kdesvnview.moc" diff --git a/src/kdesvnview.h b/src/kdesvnview.h new file mode 100644 index 0000000..d8799d0 --- /dev/null +++ b/src/kdesvnview.h @@ -0,0 +1,142 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef _KDESVNVIEW_H_ +#define _KDESVNVIEW_H_ + +#include "src/svnqt/repositorylistener.hpp" +#include <qwidget.h> +#include <kparts/part.h> + +class QPainter; +class KURL; +class kdesvnfilelist; +class KdeSvnDirList; +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QSplitter; +class KActionCollection; +class KTextBrowser; +class KProgress; + + +/** + * This is the main view class for kdesvn. Most of the non-menu, + * non-toolbar, and non-statusbar (e.g., non frame) GUI code should go + * here. + * + * @short Main view + * @author Rajko Albrecht <ral@alwins-world.de> + * @version 0.1 + */ +class kdesvnView : public QWidget,public svn::repository::RepositoryListener +{ + Q_OBJECT +public: + /** + * Default constructor + */ + kdesvnView(KActionCollection*,QWidget *parent,const char*name=0,bool full=false); + + /** + * Destructor + */ + virtual ~kdesvnView(); + + /** + * Random 'get' function + */ + QString currentURL(); + + /** + * Random 'set' function accessed by DCOP + */ + virtual bool openURL(QString url); + + /** + * Random 'set' function + */ + virtual bool openURL(const KURL& url); + + /* repositorylistener methods */ + virtual void sendWarning(const QString&); + virtual void sendError(const QString&); + virtual bool isCanceld(); + +signals: + /** + * Use this signal to change the content of the statusbar + */ + void signalChangeStatusbar(const QString&); + + /** + * Use this signal to change the content of the caption + */ + void signalChangeCaption(const QString&); + + void sigShowPopup(const QString&,QWidget**); + void sigSwitchUrl(const KURL&); + void setWindowCaption(const QString&); + void sigUrlChanged(const QString&); + void sigMakeBaseDirs(); + + /* repositorylistener methods */ + void tickProgress(); + void waitShow(bool); + +public slots: + virtual void closeMe(); + virtual void slotDispPopup(const QString&,QWidget**); + virtual void refreshCurrentTree(); + virtual void slotSettingsChanged(); + virtual void slotCreateRepo(); + virtual void slotDumpRepo(); + virtual void slotHotcopy(); + virtual void slotLoaddump(); + + /* repositorylistener methods */ + virtual void setCanceled(bool); + virtual void fillCacheStatus(Q_LONG,Q_LONG); + +protected slots: + virtual void slotOnURL(const QString& url); + virtual void slotSetTitle(const QString& title); + virtual void slotAppendLog(const QString& text); + virtual void slotUrlChanged(const QString&); + +protected: + kdesvnfilelist*m_flist; + KActionCollection*m_Collection; + + QSplitter *m_Splitter,*m_infoSplitter; + QString m_currentURL; + KTextBrowser*m_LogWindow; + QVBoxLayout*m_topLayout; + KProgress*m_CacheProgressBar; + +protected: + virtual void setupActions(); + bool m_ReposCancel; +}; + +#endif // _KDESVNVIEW_H_ diff --git a/src/kiosvn/CMakeLists.txt b/src/kiosvn/CMakeLists.txt new file mode 100644 index 0000000..5cce1af --- /dev/null +++ b/src/kiosvn/CMakeLists.txt @@ -0,0 +1,26 @@ +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/src/svnqt +${CMAKE_BINARY_DIR}/src/ksvnwidgets) + +SET(kiosvn_src kiosvn.cpp kiolistener.cpp kiobytestream.cpp ../ksvnwidgets/pwstorage.cpp) +FILE(GLOB hdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") + +KDE3_ADD_KPART(kio_ksvn ${kiosvn_src} ${hdr}) + +TARGET_LINK_LIBRARIES(kio_ksvn + svnqt + kdesvnhelpers + kdesvncfgreader + ${QT_AND_KDECORE_LIBS} + ${KDE3_UI_LIBRARY} ${KDE3_DCOP_LIBRARY} ${KDE3_KIO_LIBRARY} ${KDE3_WALLET_LIBRARY}) + +SET_TARGET_PROPERTIES(kio_ksvn + PROPERTIES + LINK_FLAG "${LINK_NO_UNDEFINED} ${_BASE_LDADD}") + +INSTALL(TARGETS kio_ksvn + LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR}) + +FILE(GLOB PROTFILES *.protocol) + +INSTALL(FILES ${PROTFILES} + DESTINATION ${SERVICES_INSTALL_DIR}) diff --git a/src/kiosvn/kiobytestream.cpp b/src/kiosvn/kiobytestream.cpp new file mode 100644 index 0000000..ff10a6a --- /dev/null +++ b/src/kiosvn/kiobytestream.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kiobytestream.h" + +KioByteStream::KioByteStream(StreamWrittenCb*aCb,const QString&filename) + : svn::stream::SvnStream(false,true,0L), + m_Cb(aCb),m_Written(0), + m_mimeSend(false),m_Filename(filename) +{ + m_MessageTick.start(); +} + +KioByteStream::~KioByteStream() +{ +} + +bool KioByteStream::isOk() const +{ + return m_Cb != 0; +} + +long KioByteStream::write(const char* data, const unsigned long max) +{ + bool forceInfo = !m_mimeSend; + if (m_Cb) { + if (!m_mimeSend) { + m_mimeSend = true; + array.setRawData(data, max); + KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType(array,m_Filename); + m_Cb->streamSendMime(result); + array.resetRawData(data, max); + m_Cb->streamTotalSizeNull(); + } + array.setRawData(data, max); + m_Cb->streamPushData(array); + array.resetRawData(data, max); + + m_Written+=max; + if (m_MessageTick.elapsed() >=100 || forceInfo) { + m_Cb->streamWritten(m_Written); + m_MessageTick.restart(); + } + return max; + } + return -1; +} diff --git a/src/kiosvn/kiobytestream.h b/src/kiosvn/kiobytestream.h new file mode 100644 index 0000000..8e62155 --- /dev/null +++ b/src/kiosvn/kiobytestream.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KIOBYTESTREAM_H +#define KIOBYTESTREAM_H + +#include "src/svnqt/svnstream.hpp" + +#include <kio/global.h> +#include <kmimetype.h> +#include <kmimemagic.h> +#include <qbuffer.h> +#include <qdatetime.h> + +class StreamWrittenCb +{ +public: + StreamWrittenCb(){} + virtual ~StreamWrittenCb(){} + virtual void streamWritten(const KIO::filesize_t current) = 0; + virtual void streamPushData(QByteArray)=0; + virtual void streamSendMime(KMimeMagicResult*mt)=0; + virtual void streamTotalSizeNull()=0; +}; + +/** + @author Rajko Albrecht +*/ +class KioByteStream : public svn::stream::SvnStream +{ +public: + KioByteStream(StreamWrittenCb*,const QString&filename); + + ~KioByteStream(); + + virtual bool isOk() const; + virtual long write(const char* data, const unsigned long max); + + KIO::filesize_t written(){return m_Written;} + +protected: + StreamWrittenCb*m_Cb; + KIO::filesize_t m_Written; + bool m_mimeSend; + QString m_Filename; + QByteArray array; + QTime m_MessageTick; +}; + +#endif diff --git a/src/kiosvn/kiolistener.cpp b/src/kiosvn/kiolistener.cpp new file mode 100644 index 0000000..f3b7b68 --- /dev/null +++ b/src/kiosvn/kiolistener.cpp @@ -0,0 +1,408 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kiolistener.h" +#include "kiosvn.h" + +#include <kdebug.h> +#include <klocale.h> +#include <dcopclient.h> + +namespace KIO { + +KioListener::KioListener(KIO::kio_svnProtocol*_par) + : svn::ContextListener(),m_notifyCounter(0),m_External(false),m_HasChanges(false),m_FirstTxDelta(false),m_Canceld(false) +{ + par = _par; +} + + +KioListener::~KioListener() +{ +} + + + + +/*! + \fn KioListener::contextCancel() + */ +bool KioListener::contextCancel() +{ + return par->wasKilled()||m_Canceld; +} + + +/*! + \fn KioListener::contextGetLogMessage (QString & msg) + */ +bool KioListener::contextGetLogMessage (QString & msg,const svn::CommitItemList&_items) +{ +#if 1 + QByteArray reply; + QByteArray params; + QCString replyType; + QDataStream stream(params,IO_WriteOnly); + + if (_items.count()>0) { + QMap<QString,QString> list; + for (unsigned i = 0;i<_items.count();++i) { + if (_items[i].path().isEmpty()) { + list[_items[i].url()]=QChar(_items[i].actionType()); + } else { + list[_items[i].path()]=QChar(_items[i].actionType()); + } + } + stream << list; + if (!par->dcopClient()->call("kded","kdesvnd","get_logmsg(QMap<QString,QString>)",params,replyType,reply)) { + msg = "Communication with dcop failed"; + kdWarning()<<msg<<endl; + return false; + } + } else { + if (!par->dcopClient()->call("kded","kdesvnd","get_logmsg()",params,replyType,reply)) { + msg = "Communication with dcop failed"; + kdWarning()<<msg<<endl; + return false; + } + } + + if (replyType!="QStringList") { + msg = "Wrong reply type"; + kdWarning()<<msg<<endl; + return false; + } + QDataStream stream2(reply,IO_ReadOnly); + QStringList lt; + stream2>>lt; + if (lt.count()!=1) { + msg = "Wrong or missing log (may cancel pressed)."; + kdDebug()<< msg << endl; + return false; + } + msg = lt[0]; +#else + msg = "Made with a kio::svn client"; +#endif + return true; +} + +/*! the content of that method is taken from the notify in kio::svn in KDE SDK */ +/* this moment we don't use it full 'cause not all is made via KIO */ +void KioListener::contextNotify (const char * path,svn_wc_notify_action_t action,svn_node_kind_t kind ,const char * mime_type ,svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state,svn_revnum_t revision) +{ + if (par->wasKilled()) { + return; + } + QString userstring; + + switch(action) { + case svn_wc_notify_add: + { + if (mime_type && (svn_mime_type_is_binary (mime_type))) + userstring = i18n( "A (bin) %1" ).arg( path ); + else + userstring = i18n( "A %1" ).arg( path ); + break; + } + break; + case svn_wc_notify_copy: //copy + break; + case svn_wc_notify_delete: //delete + m_HasChanges = TRUE; + userstring = i18n( "D %1" ).arg( path ); + break; + case svn_wc_notify_restore : //restore + userstring=i18n( "Restored %1." ).arg( path ); + break; + case svn_wc_notify_revert : //revert + userstring=i18n( "Reverted %1." ).arg( path ); + break; + case svn_wc_notify_failed_revert: //failed revert + userstring=i18n( "Failed to revert %1.\nTry updating instead." ).arg( path ); + break; + case svn_wc_notify_resolved: //resolved + userstring=i18n( "Resolved conflicted state of %1." ).arg( path ); + break; + case svn_wc_notify_skip: //skip + if ( content_state == svn_wc_notify_state_missing ) + userstring=i18n("Skipped missing target %1.").arg( path ); + else + userstring=i18n("Skipped %1.").arg( path ); + break; + case svn_wc_notify_update_delete: //update_delete + m_HasChanges = TRUE; + userstring=i18n( "D %1" ).arg( path ); + break; + case svn_wc_notify_update_add: //update_add + m_HasChanges = TRUE; + userstring=i18n( "A %1" ).arg( path ); + break; + case svn_wc_notify_update_update: //update_update + { + /* If this is an inoperative dir change, do no notification. + An inoperative dir change is when a directory gets closed + without any props having been changed. */ + if (! ((kind == svn_node_dir) + && ((prop_state == svn_wc_notify_state_inapplicable) + || (prop_state == svn_wc_notify_state_unknown) + || (prop_state == svn_wc_notify_state_unchanged)))) { + m_HasChanges = TRUE; + + if (kind == svn_node_file) { + if (content_state == svn_wc_notify_state_conflicted) + userstring = "C"; + else if (content_state == svn_wc_notify_state_merged) + userstring = "G"; + else if (content_state == svn_wc_notify_state_changed) + userstring = "U"; + } + + if (prop_state == svn_wc_notify_state_conflicted) + userstring += "C"; + else if (prop_state == svn_wc_notify_state_merged) + userstring += "G"; + else if (prop_state == svn_wc_notify_state_changed) + userstring += "U"; + else + userstring += " "; + + if (! ((content_state == svn_wc_notify_state_unchanged + || content_state == svn_wc_notify_state_unknown) + && (prop_state == svn_wc_notify_state_unchanged + || prop_state == svn_wc_notify_state_unknown))) + userstring += QString( " " ) + path; + } + break; + } + case svn_wc_notify_update_completed: //update_completed + { + if (!m_External) { + if (SVN_IS_VALID_REVNUM(revision)) { + userstring = i18n("Finished at revision %1.").arg(revision); + } else { + userstring = i18n("Finished."); + } + } else { + if (SVN_IS_VALID_REVNUM(revision)) { + userstring = i18n("Finished external at revision %1.").arg(revision); + } else { + userstring = i18n("Finished external."); + } + } + } + if (m_External) + m_External = FALSE; + break; + case svn_wc_notify_update_external: //update_external + m_External = TRUE; + userstring = i18n("Fetching external item into %1." ).arg( path ); + break; + case svn_wc_notify_status_completed: //status_completed + if (SVN_IS_VALID_REVNUM (revision)) + userstring = i18n( "Status against revision: %1.").arg( revision ); + break; + case svn_wc_notify_status_external: //status_external + userstring = i18n("Performing status on external item at %1.").arg( path ); + break; + case svn_wc_notify_commit_modified: //commit_modified + userstring = i18n( "Sending %1.").arg( path ); + break; + case svn_wc_notify_commit_added: //commit_added + if (mime_type && svn_mime_type_is_binary (mime_type)) { + userstring = i18n( "Adding (bin) %1.").arg( path ); + } else { + userstring = i18n( "Adding %1.").arg( path ); + } + break; + case svn_wc_notify_commit_deleted: //commit_deleted + userstring = i18n( "Deleting %1.").arg( path ); + break; + case svn_wc_notify_commit_replaced: //commit_replaced + userstring = i18n( "Replacing %1.").arg( path ); + break; + case svn_wc_notify_commit_postfix_txdelta: //commit_postfix_txdelta + if (!m_FirstTxDelta) { + m_FirstTxDelta = TRUE; + // check fullstops! + userstring=i18n("Transmitting file data "); + } else { + userstring="."; + } + break; + + break; + case svn_wc_notify_blame_revision: //blame_revision + break; + default: + break; + } + par->setMetaData(QString::number(counter()).rightJustify( 10,'0' )+ "path" , QString::FROMUTF8( path )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "action", QString::number( action )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "kind", QString::number( kind )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "mime_t", QString::FROMUTF8( mime_type )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "content", QString::number( content_state )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "prop", QString::number( prop_state )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "rev", QString::number( revision )); + par->setMetaData(QString::number( counter() ).rightJustify( 10,'0' )+ "string", userstring ); + incCounter(); +} + +void KioListener::contextNotify (const svn_wc_notify_t *action) +{ + if (!action) return; +// if (action->action<svn_wc_notify_locked) { + contextNotify(action->path,action->action,action->kind,action->mime_type, + action->content_state,action->prop_state,action->revision); +// return; +// } +// QString aString = NotifyAction(action->action); +} + +svn::ContextListener::SslServerTrustAnswer +KioListener::contextSslServerTrustPrompt (const SslServerTrustData & data, apr_uint32_t & acceptedFailures) +{ + QByteArray reply; + QByteArray params; + QCString replyType; + QDataStream stream(params,IO_WriteOnly); + stream << data.hostname + << data.fingerprint + << data.validFrom + << data.validUntil + << data.issuerDName + << data.realm; + + if (!par->dcopClient()->call("kded","kdesvnd", + "get_sslaccept(QString,QString,QString,QString,QString,QString)", + params,replyType,reply)) { + kdWarning()<<"Communication with dcop failed"<<endl; + return DONT_ACCEPT; + } + if (replyType!="int") { + kdWarning()<<"Wrong reply type"<<endl; + return DONT_ACCEPT; + } + QDataStream stream2(reply,IO_ReadOnly); + int res; + stream2>>res; + switch (res) { + case -1: + return DONT_ACCEPT; + break; + case 1: + return ACCEPT_PERMANENTLY; + break; + default: + case 0: + return ACCEPT_TEMPORARILY; + break; + } + /* avoid compiler warnings */ + return ACCEPT_TEMPORARILY; +} + +bool KioListener::contextLoadSslClientCertPw(QString&password,const QString&realm) +{ + return PwStorage::self()->getCertPw(realm,password); +} + +bool KioListener::contextSslClientCertPrompt (QString & certFile) +{ + QByteArray reply; + QByteArray params; + QCString replyType; + if (!par->dcopClient()->call("kded","kdesvnd", + "get_sslclientcertfile()", + params,replyType,reply)) { + kdWarning()<<"Communication with dcop failed"<<endl; + return false; + } + if (replyType!="QString") { + kdWarning()<<"Wrong reply type"<<endl; + return false; + } + QDataStream stream2(reply,IO_ReadOnly); + stream2>>certFile; + if (certFile.isEmpty()) { + return false; + } + return true; +} + +bool KioListener::contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maySave) +{ + return false; +} + +bool KioListener::contextGetSavedLogin (const QString & realm,QString & username,QString & password) +{ + PwStorage::self()->getLogin(realm,username,password); + return true; +} + +bool KioListener::contextGetCachedLogin (const QString & realm,QString & username,QString & password) +{ + return true; +} + +bool KioListener::contextGetLogin (const QString & realm, QString & username, QString & password, bool & maySave) +{ + QByteArray reply; + QByteArray params; + QCString replyType; + + QDataStream stream(params,IO_WriteOnly); + stream << realm; + stream << username; + + if (!par->dcopClient()->call("kded","kdesvnd","get_login(QString,QString)",params,replyType,reply)) { + kdWarning()<<"Communication with dcop failed"<<endl; + return false; + } + if (replyType!="QStringList") { + kdWarning()<<"Wrong reply type"<<endl; + return false; + } + QDataStream stream2(reply,IO_ReadOnly); + QStringList lt; + stream2>>lt; + if (lt.count()!=3) { + kdDebug()<<"Wrong or missing auth list (may cancel pressed)." << endl; + return false; + } + username = lt[0]; + password = lt[1]; + maySave = lt[2]=="true"; + return true; +} + + +/*! + \fn KioListener::contextProgress(long long int current, long long int max) + */ +void KioListener::contextProgress(long long int cur, long long int max) +{ + if (par) { + par->contextProgress(cur,max); + } +} + +} // namespace KIO diff --git a/src/kiosvn/kiolistener.h b/src/kiosvn/kiolistener.h new file mode 100644 index 0000000..96a1629 --- /dev/null +++ b/src/kiosvn/kiolistener.h @@ -0,0 +1,83 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KIOLISTENER_H +#define KIOLISTENER_H + +#include "src/svnqt/context_listener.hpp" +#include "src/ksvnwidgets/pwstorage.h" + +namespace KIO { + class SlaveBase; + class kio_svnProtocol; + +/** +@author Rajko Albrecht +*/ +class KioListener : public svn::ContextListener +{ +public: + KioListener(KIO::kio_svnProtocol*_par); + virtual ~KioListener(); + + /* context-listener methods */ + virtual bool contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave); + virtual bool contextGetSavedLogin (const QString & realm,QString & username,QString & password); + virtual bool contextGetCachedLogin (const QString & realm,QString & username,QString & password); + + virtual void contextNotify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision); + virtual void contextNotify (const svn_wc_notify_t *action); + + virtual bool contextCancel(); + virtual bool contextGetLogMessage (QString & msg,const svn::CommitItemList&); + virtual SslServerTrustAnswer contextSslServerTrustPrompt (const SslServerTrustData & data, + apr_uint32_t & acceptedFailures); + virtual bool contextSslClientCertPrompt (QString & certFile); + virtual bool contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maySave); + virtual bool contextLoadSslClientCertPw(QString&password,const QString&realm); + /* context listener virtuals end */ + unsigned int counter()const{return m_notifyCounter;} + void incCounter(){++m_notifyCounter;} + virtual void contextProgress(long long int current, long long int max); + + void setCancel(bool value){m_Canceld=value;} + +private: + KIO::kio_svnProtocol *par; + +protected: + unsigned int m_notifyCounter; + bool m_External; + bool m_HasChanges; + bool m_FirstTxDelta; + bool m_Canceld; +}; +} + +#endif diff --git a/src/kiosvn/kiosvn.cpp b/src/kiosvn/kiosvn.cpp new file mode 100644 index 0000000..667d456 --- /dev/null +++ b/src/kiosvn/kiosvn.cpp @@ -0,0 +1,954 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kdesvn-config.h" +#include "kiosvn.h" +#include "kiolistener.h" + +#include "src/svnqt/svnqttypes.hpp" +#include "src/svnqt/dirent.hpp" +#include "src/svnqt/url.hpp" +#include "src/svnqt/status.hpp" +#include "src/svnqt/targets.hpp" +#include "src/svnqt/info_entry.hpp" +#include "src/settings/kdesvnsettings.h" +#include "src/helpers/sub2qt.h" +#include "src/helpers/sshagent.h" + +#include <stdlib.h> +#include <math.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdemacros.h> +#include <kmessagebox.h> +#include <kinstance.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <klocale.h> +#include <kurl.h> +#include <ktempdir.h> +#include <ksock.h> +#include <dcopclient.h> +#include <qcstring.h> +#include <kmimetype.h> +#include <krun.h> +#include <qtextstream.h> + +#include <stdlib.h> +#include <math.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +namespace KIO +{ + +class KioSvnData +{ +public: + KioSvnData(kio_svnProtocol*); + virtual ~KioSvnData(); + + void reInitClient(); + + KioListener m_Listener; + bool first_done; + bool dispProgress; + svn::ContextP m_CurrentContext; + svn::Client* m_Svnclient; + + svn::Revision urlToRev(const KURL&); + +}; + +KioSvnData::KioSvnData(kio_svnProtocol*par) + : m_Listener(par),first_done(false) +{ + m_Svnclient=svn::Client::getobject(0,0); + m_CurrentContext = 0; + dispProgress = false; + reInitClient(); +} + +void KioSvnData::reInitClient() +{ + if (first_done) { + return; + } + SshAgent ag; + ag.querySshAgent(); + + first_done = true; + m_CurrentContext = new svn::Context(); + m_CurrentContext->setListener(&m_Listener); + m_Svnclient->setContext(m_CurrentContext); +} + +KioSvnData::~KioSvnData() +{ + m_Listener.setCancel(true); + /* wait a little bit */ + sleep(1); + delete m_Svnclient; + m_CurrentContext->setListener(0L); + m_CurrentContext = 0; +} + +svn::Revision KioSvnData::urlToRev(const KURL&url) +{ + QMap<QString,QString> q = url.queryItems(); + + /* we try to check if it is ssh and try to get a password for it */ + QString proto = url.protocol(); + + if (proto.find("ssh")!=-1) { + SshAgent ag; + ag.addSshIdentities(); + } + + svn::Revision rev,tmp; + rev = svn::Revision::UNDEFINED; + if (q.find("rev")!=q.end()) { + QString v = q["rev"]; + m_Svnclient->url2Revision(v,rev,tmp); + } + return rev; +} + + +kio_svnProtocol::kio_svnProtocol(const QCString &pool_socket, const QCString &app_socket) + : SlaveBase("kio_ksvn", pool_socket, app_socket),StreamWrittenCb() +{ + m_pData=new KioSvnData(this); + KGlobal::locale()->insertCatalogue("kdesvn"); +} + +kio_svnProtocol::~kio_svnProtocol() +{ + kdDebug()<<"Delete kio protocol"<<endl; + delete m_pData; +} + +} + +extern "C" +{ + KDESVN_EXPORT int kdemain(int argc, char **argv); +} + +int kdemain(int argc, char **argv) +{ + kdDebug()<<"kdemain" << endl; + KInstance instance( "kio_ksvn" ); + // start the kdesvnd DCOP service + QString error; + QCString appId; + + kdDebug(7101) << "*** Starting kio_ksvn " << endl; + + if (argc != 4) { + kdDebug(7101) << "Usage: kio_ksvn protocol domain-socket1 domain-socket2" << endl; + exit(-1); + } + + KIO::kio_svnProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + + kdDebug(7101) << "*** kio_ksvn Done" << endl; + return 0; +} + +namespace KIO +{ +/*! + \fn kio_svnProtocol::listDir (const KURL&url) + */ +void kio_svnProtocol::listDir(const KURL&url) +{ + kdDebug() << "kio_svn::listDir(const KURL& url) : " << url.url() << endl ; + svn::DirEntries dlist; + svn::Revision rev = m_pData->urlToRev(url); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + + try { + dlist = m_pData->m_Svnclient->list(makeSvnUrl(url),rev,rev,svn::DepthImmediates,false); + } catch (const svn::ClientException&e) { + QString ex = e.msg(); + kdDebug()<<ex<<endl; + error(KIO::ERR_CANNOT_ENTER_DIRECTORY,ex); + return; + } + KIO::UDSEntry entry; + totalSize(dlist.size()); + for (unsigned int i=0; i < dlist.size();++i) { + if (!dlist[i] || dlist[i]->name().isEmpty()) { + continue; + } + QDateTime dt = svn::DateTime(dlist[i]->time()); + if (createUDSEntry(dlist[i]->name(), + dlist[i]->lastAuthor(), + dlist[i]->size(), + dlist[i]->kind()==svn_node_dir?true:false, + dt.toTime_t(), + entry) ) { + listEntry(entry,false); + } + entry.clear(); + } + listEntry(entry, true ); + finished(); +} + +void kio_svnProtocol::stat(const KURL& url) +{ + kdDebug()<<"kio_svn::stat "<< url << endl; + svn::Revision rev = m_pData->urlToRev(url); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + svn::Revision peg = rev; + bool dummy = false; + svn::InfoEntries e; + try { + e = m_pData->m_Svnclient->info(makeSvnUrl(url),svn::DepthEmpty,rev,peg); + } catch (const svn::ClientException&e) { + QString ex = e.msg(); + kdDebug()<<ex<<endl; + error( KIO::ERR_SLAVE_DEFINED,ex); + return; + } + + if (e.count()==0) { + dummy = true; +/* finished(); + return;*/ + } + + KIO::UDSEntry entry; + QDateTime dt; + if (dummy) { + createUDSEntry(url.filename(),"",0,true,dt.toTime_t(),entry); + } else { + dt = svn::DateTime(e[0].cmtDate()); + if (e[0].kind()==svn_node_file) { + createUDSEntry(url.filename(),"",0,false,dt.toTime_t(),entry); + } else { + createUDSEntry(url.filename(),"",0,true,dt.toTime_t(),entry); + } + } + statEntry(entry); + finished(); +} + +void kio_svnProtocol::get(const KURL& url) +{ + kdDebug()<<"kio_svn::get "<< url << endl; + if (m_pData->m_Listener.contextCancel()) { + finished(); + return; + } + svn::Revision rev = m_pData->urlToRev(url); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + KioByteStream dstream(this,url.filename()); + try { + m_pData->m_Svnclient->cat(dstream,makeSvnUrl(url),rev,rev); + } catch (const svn::ClientException&e) { + QString ex = e.msg(); + kdDebug()<<ex<<endl; + error( KIO::ERR_SLAVE_DEFINED,"Subversion error "+ex); + finished(); + return; + } + totalSize(dstream.written()); + data(QByteArray()); // empty array means we're done sending the data + finished(); +} + +void kio_svnProtocol::mkdir(const KURL &url, int) +{ + kdDebug()<<"kio_svn::mkdir "<< url << endl; + svn::Revision rev = m_pData->urlToRev(url); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + try { + svn::Path p(makeSvnUrl(url)); + m_pData->m_Svnclient->mkdir(p,getDefaultLog()); + }catch (const svn::ClientException&e) { + error( KIO::ERR_SLAVE_DEFINED,e.msg()); + } + kdDebug()<<"kio_svn::mkdir finished " << url << endl; + finished(); +} + +void kio_svnProtocol::mkdir(const KURL::List &urls, int) +{ + svn::Pathes p; + for ( QValueListConstIterator<KURL> it = urls.begin(); it != urls.end() ; ++it ) { + p.append((*it).path()); + } + try { + m_pData->m_Svnclient->mkdir(svn::Targets(p),getDefaultLog()); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + finished(); +} + +void kio_svnProtocol::rename(const KURL&src,const KURL&target,bool force) +{ + kdDebug()<<"kio_svn::rename "<< src << " to " << target << endl; + QString msg; + m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); + try { + m_pData->m_Svnclient->move(makeSvnUrl(src),makeSvnUrl(target),force); + }catch (const svn::ClientException&e) { + error( KIO::ERR_SLAVE_DEFINED,e.msg()); + } + kdDebug()<<"kio_svn::rename finished" << endl; + finished(); +} + +void kio_svnProtocol::copy(const KURL&src,const KURL&dest,int permissions,bool overwrite) +{ + Q_UNUSED(permissions); + Q_UNUSED(overwrite); + kdDebug()<<"kio_svn::copy "<< src << " to " << dest << endl; + svn::Revision rev = m_pData->urlToRev(src); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + m_pData->dispProgress=true; + m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); + try { + m_pData->m_Svnclient->copy(makeSvnUrl(src),rev,makeSvnUrl(dest)); + }catch (const svn::ClientException&e) { + error( KIO::ERR_SLAVE_DEFINED,e.msg()); + } + m_pData->dispProgress=false; + kdDebug()<<"kio_svn::copy finished" << endl; + finished(); +} + +void kio_svnProtocol::del(const KURL&src,bool isfile) +{ + Q_UNUSED(isfile); + kdDebug()<<"kio_svn::del "<< src << endl; + //m_pData->reInitClient(); + svn::Revision rev = m_pData->urlToRev(src); + if (rev == svn::Revision::UNDEFINED) { + rev = svn::Revision::HEAD; + } + m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); + try { + svn::Targets target(makeSvnUrl(src)); + m_pData->m_Svnclient->remove(target,false); + } catch (const svn::ClientException&e) { + QString ex = e.msg(); + kdDebug()<<ex<<endl; + error( KIO::ERR_SLAVE_DEFINED,ex); + } + kdDebug()<<"kio_svn::del finished" << endl; + finished(); +} + +bool kio_svnProtocol::getLogMsg(QString&t) +{ + svn::CommitItemList _items; + return m_pData->m_Listener.contextGetLogMessage(t,_items); +} + +bool kio_svnProtocol::checkWc(const KURL&url) +{ + if (url.isEmpty()||!url.isLocalFile()) return false; + svn::Revision peg(svn_opt_revision_unspecified); + svn::Revision rev(svn_opt_revision_unspecified); + svn::InfoEntries e; + try { + e = m_pData->m_Svnclient->info(url.prettyURL(),svn::DepthEmpty,rev,peg); + } catch (const svn::ClientException&e) { + if (SVN_ERR_WC_NOT_DIRECTORY==e.apr_err()) + { + return false; + } + return true; + } + return false; +} + +QString kio_svnProtocol::makeSvnUrl(const KURL&url,bool check_Wc) +{ + QString res; + QString proto = svn::Url::transformProtokoll(url.protocol()); + if (proto=="file" && check_Wc) + { + if (checkWc(url)) + { + return url.path(); + } + } + + QStringList s = QStringList::split("://",res); + QString base = url.path(); + QString host = url.host(); + QString user = (url.hasUser()?url.user()+(url.hasPass()?":"+url.pass():""):""); + if (host.isEmpty()) { + res=proto+"://"+base; + } else { + res = proto+"://"+(user.isEmpty()?"":user+"@")+host+base; + } + if (base.isEmpty()) { + throw svn::ClientException(QString("'")+res+QString("' is not a valid subversion url")); + } + return res; +} + +bool kio_svnProtocol::createUDSEntry( const QString& filename, const QString& user, long long int size, bool isdir, time_t mtime, KIO::UDSEntry& entry) +{ +#if 0 + kdDebug() << "MTime : " << ( long )mtime << endl; + kdDebug() << "UDS filename : " << filename << endl; + kdDebug()<< "UDS Size: " << size << endl; + kdDebug()<< "UDS Dir: " << isdir << endl; +#endif + KIO::UDSAtom atom; + atom.m_uds = KIO::UDS_NAME; + atom.m_str = filename; + entry.append( atom ); + + atom.m_uds = KIO::UDS_FILE_TYPE; + atom.m_long = isdir ? S_IFDIR : S_IFREG; + entry.append( atom ); + + atom.m_uds = KIO::UDS_ACCESS; + atom.m_long = isdir?0777:0666; + entry.append(atom); + + + atom.m_uds = KIO::UDS_SIZE; + atom.m_long = size; + entry.append( atom ); + + atom.m_uds = KIO::UDS_MODIFICATION_TIME; + atom.m_long = mtime; + entry.append( atom ); + + atom.m_uds = KIO::UDS_USER; + atom.m_str = user; + entry.append( atom ); + + return true; +} + +void kio_svnProtocol::special(const QByteArray& data) +{ + kdDebug()<<"kio_svnProtocol::special"<<endl; + QDataStream stream(data,IO_ReadOnly); + int tmp; + stream >> tmp; + kdDebug() << "kio_svnProtocol::special " << tmp << endl; + switch (tmp) { + case SVN_CHECKOUT: + { + KURL repository, wc; + int revnumber; + QString revkind; + stream >> repository; + stream >> wc; + stream >> revnumber; + stream >> revkind; + kdDebug(0) << "kio_svnProtocol CHECKOUT from " << repository.url() << " to " << wc.url() << " at " << revnumber << " or " << revkind << endl; + checkout( repository, wc, revnumber, revkind ); + break; + } + case SVN_UPDATE: + { + KURL wc; + int revnumber; + QString revkind; + stream >> wc; + stream >> revnumber; + stream >> revkind; + kdDebug(0) << "kio_svnProtocol UPDATE " << wc.url() << " at " << revnumber << " or " << revkind << endl; + update(wc, revnumber, revkind ); + break; + } + case SVN_COMMIT: + { + KURL::List wclist; + while ( !stream.atEnd() ) { + KURL tmp; + stream >> tmp; + wclist << tmp; + } + kdDebug(0) << "kio_svnProtocol COMMIT" << endl; + commit( wclist ); + break; + } + case SVN_LOG: + { + kdDebug(0) << "kio_svnProtocol LOG" << endl; + int revstart, revend; + QString revkindstart, revkindend; + KURL::List targets; + stream >> revstart; + stream >> revkindstart; + stream >> revend; + stream >> revkindend; + while ( !stream.atEnd() ) { + KURL tmp; + stream >> tmp; + targets << tmp; + } + svnlog( revstart, revkindstart, revend, revkindend, targets ); + break; + } + case SVN_IMPORT: + { + KURL wc,repos; + stream >> repos; + stream >> wc; + kdDebug(0) << "kio_ksvnProtocol IMPORT" << endl; + import(repos,wc); + break; + } + case SVN_ADD: + { + KURL wc; + kdDebug(0) << "kio_ksvnProtocol ADD" << endl; + stream >> wc; + add(wc); + break; + } + case SVN_DEL: + { + KURL::List wclist; + while ( !stream.atEnd() ) { + KURL tmp; + stream >> tmp; + wclist << tmp; + } + wc_delete(wclist); + break; + } + case SVN_REVERT: + { + KURL::List wclist; + while ( !stream.atEnd() ) { + KURL tmp; + stream >> tmp; + wclist << tmp; + } + kdDebug(7128) << "kio_svnProtocol REVERT" << endl; + revert(wclist); + break; + } + case SVN_STATUS: + { + KURL wc; + bool checkRepos=false; + bool fullRecurse=false; + stream >> wc; + stream >> checkRepos; + stream >> fullRecurse; + kdDebug(0) << "kio_svnProtocol STATUS" << endl; + status(wc,checkRepos,fullRecurse); + break; + } + case SVN_MKDIR: + { + KURL::List list; + stream >> list; + kdDebug(0) << "kio_svnProtocol MKDIR" << endl; + mkdir(list,0); + break; + } + case SVN_RESOLVE: + { + KURL url; + bool recurse; + stream >> url; + stream >> recurse; + kdDebug(7128) << "kio_svnProtocol RESOLVE" << endl; + wc_resolve(url,recurse); + break; + } + case SVN_SWITCH: + { + KURL wc,url; + bool recurse; + int revnumber; + QString revkind; + stream >> wc; + stream >> url; + stream >> recurse; + stream >> revnumber; + stream >> revkind; + kdDebug(7128) << "kio_svnProtocol SWITCH" << endl; + wc_switch(wc,url,recurse,revnumber,revkind); + break; + } + case SVN_DIFF: + { + KURL url1,url2; + int rev1, rev2; + bool recurse; + QString revkind1, revkind2; + stream >> url1; + stream >> url2; + stream >> rev1; + stream >> revkind1; + stream >> rev2; + stream >> revkind2; + stream >> recurse; + diff(url1,url2,rev1,revkind1,rev2,revkind2,recurse); + break; + } + default: + {kdDebug()<<"Unknown special" << endl;} + } + finished(); +} + +void kio_svnProtocol::update(const KURL&url,int revnumber,const QString&revkind) +{ + svn::Revision where(revnumber,revkind); + /* update is always local - so make a path instead URI */ + svn::Path p(url.path()); + try { + svn::Targets pathes(p.path()); + // always update externals, too. (third last parameter) + // no unversioned items allowed (second last parameter) + // sticky depth (last parameter) + m_pData->m_Svnclient->update(pathes, where,svn::DepthInfinity,false,false,true); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + } +} + +void kio_svnProtocol::status(const KURL&wc,bool cR,bool rec) +{ + svn::Revision where = svn::Revision::UNDEFINED; + svn::StatusEntries dlist; + try { + // rec all up noign + dlist = m_pData->m_Svnclient->status(wc.path(),rec?svn::DepthInfinity:svn::DepthEmpty,false,cR,false,where); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + kdDebug()<<"Status got " << dlist.count() << " entries." << endl; + for (unsigned j=0;j<dlist.count();++j) { + if (!dlist[j]) { + continue; + } + //QDataStream stream(params, IO_WriteOnly); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+"path",dlist[j]->path()); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+"text",QString::number(dlist[j]->textStatus())); + setMetaData(QString::number(m_pData->m_Listener.counter() ).rightJustify( 10,'0' )+ "prop", + QString::number(dlist[j]->propStatus())); + setMetaData(QString::number(m_pData->m_Listener.counter() ).rightJustify( 10,'0' )+ "reptxt", + QString::number(dlist[j]->reposTextStatus())); + setMetaData(QString::number(m_pData->m_Listener.counter() ).rightJustify( 10,'0' )+ "repprop", + QString::number(dlist[j]->reposPropStatus())); + setMetaData(QString::number(m_pData->m_Listener.counter() ).rightJustify( 10,'0' )+ "rev", + QString::number(dlist[j]->entry().cmtRev())); + m_pData->m_Listener.incCounter(); + } +} + +void kio_svnProtocol::commit(const KURL::List&url) +{ + /// @todo replace with direct call to kdesvn? + QByteArray reply; + QByteArray params; + QCString replyType; + QString msg; + + if (!dcopClient()->call("kded","kdesvnd","get_logmsg()",params,replyType,reply)) { + msg = "Communication with dcop failed"; + kdWarning()<<msg<<endl; + return; + } + if (replyType!="QStringList") { + msg = "Wrong reply type"; + kdWarning()<<msg<<endl; + return; + } + QDataStream stream2(reply,IO_ReadOnly); + QStringList lt; + stream2>>lt; + if (lt.count()!=1) { + msg = "Wrong or missing log (may cancel pressed)."; + kdDebug()<< msg << endl; + return; + } + msg = lt[0]; + QValueList<svn::Path> targets; + for (unsigned j=0; j<url.count();++j) { + targets.push_back(svn::Path(url[j].path())); + } + svn::Revision nnum=svn::Revision::UNDEFINED; + try { + nnum = m_pData->m_Svnclient->commit(svn::Targets(targets),msg,svn::DepthInfinity,false); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + } + for (unsigned j=0;j<url.count();++j) { + QString userstring; + if (nnum!=svn::Revision::UNDEFINED) { + userstring = i18n( "Committed revision %1." ).arg(nnum.toString()); + } else { + userstring = i18n ( "Nothing to commit." ); + } + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "path", url[j].path() ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "action", "0" ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "kind", "0" ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "mime_t", "" ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "content", "0" ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "prop", "0" ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "rev" , QString::number(nnum) ); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "string", userstring ); + m_pData->m_Listener.incCounter(); + } +} + +void kio_svnProtocol::checkout(const KURL&src,const KURL&target,const int rev, const QString&revstring) +{ + svn::Revision where(rev,revstring); + svn::Revision peg = svn::Revision::UNDEFINED; + svn::Path _target(target.path()); + try { + KURL _src = makeSvnUrl(src); + m_pData->m_Svnclient->checkout(_src.url(),_target,where,peg,svn::DepthInfinity,false,false); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + } +} + +void kio_svnProtocol::svnlog(int revstart,const QString&revstringstart,int revend, const QString&revstringend, const KURL::List&urls) +{ + svn::Revision start(revstart,revstringstart); + svn::Revision end(revend,revstringend); + svn::LogEntriesPtr logs; + + for (unsigned j = 0; j<urls.count();++j) { + logs = 0; + try { + logs = m_pData->m_Svnclient->log(makeSvnUrl(urls[j]),start,end,svn::Revision::UNDEFINED,true,true,0); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + break; + } + if (!logs) { + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify(10,'0')+"path",urls[j].path()); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify(10,'0')+"string", + i18n("Empty logs")); + m_pData->m_Listener.incCounter(); + continue; + } + for (unsigned int i = 0; i < logs->count();++i) { + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "path",urls[j].path()); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "rev", + QString::number( (*logs)[i].revision)); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+"author", + (*logs)[i].author); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+"logmessage", + (*logs)[i].message); + m_pData->m_Listener.incCounter(); + for (unsigned z = 0; z<(*logs)[i].changedPaths.count();++z) { + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "rev", + QString::number( (*logs)[i].revision)); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "path",urls[j].path()); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "loggedpath", + (*logs)[i].changedPaths[z].path); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "loggedaction", + QChar((*logs)[i].changedPaths[z].action)); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "loggedcopyfrompath", + (*logs)[i].changedPaths[z].copyFromPath); + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "loggedcopyfromrevision", + QString::number((*logs)[i].changedPaths[z].copyFromRevision)); + m_pData->m_Listener.incCounter(); + } + } + } +} + +void kio_svnProtocol::revert(const KURL::List&l) +{ + QValueList<svn::Path> list; + for (unsigned j=0; j<l.count();++j) { + list.append(svn::Path(l[j].path())); + } + svn::Targets target(list); + try { + m_pData->m_Svnclient->revert(target,svn::DepthEmpty); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + } +} + +void kio_svnProtocol::wc_switch(const KURL&wc,const KURL&target,bool rec,int rev,const QString&revstring) +{ + svn::Revision where(rev,revstring); + svn::Path wc_path(wc.path()); + try { + m_pData->m_Svnclient->doSwitch(wc_path,makeSvnUrl(target.url()),where,rec?svn::DepthInfinity:svn::DepthFiles); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + } +} + +void kio_svnProtocol::diff(const KURL&uri1,const KURL&uri2,int rnum1,const QString&rstring1,int rnum2, const QString&rstring2,bool rec) +{ + QByteArray ex; + /// @todo read settings for diff (ignore contentype) + try { + svn::Revision r1(rnum1,rstring1); + svn::Revision r2(rnum2,rstring2); + QString u1 = makeSvnUrl(uri1,true); + QString u2 = makeSvnUrl(uri2,true); + KTempDir tdir; + kdDebug() << "kio_ksvn::diff : " << u1 << " at revision " << r1.toString() << " with " + << u2 << " at revision " << r2.toString() + << endl ; + + tdir.setAutoDelete(true); + ex = m_pData->m_Svnclient->diff(svn::Path(tdir.name()), + u1,u2,svn::Path(),r1, r2,rec?svn::DepthInfinity:svn::DepthEmpty,false,false,false); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + QString out = QString::FROMUTF8(ex); + QTextIStream stream(&out); + while (!stream.atEnd()) { + setMetaData(QString::number(m_pData->m_Listener.counter()).rightJustify( 10,'0' )+ "diffresult",stream.readLine()); + m_pData->m_Listener.incCounter(); + } +} + +void kio_svnProtocol::import(const KURL& repos, const KURL& wc) +{ + try { + QString target = makeSvnUrl(repos); + QString path = wc.path(); + m_pData->m_Svnclient->import(svn::Path(path),target,QString::null,svn::DepthInfinity,false,false); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + finished(); +} + +void kio_svnProtocol::add(const KURL& wc) +{ + QString path = wc.path(); + try { + /* rec */ + m_pData->m_Svnclient->add(svn::Path(path),svn::DepthInfinity); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + finished(); +} + +void kio_svnProtocol::wc_delete(const KURL::List&l) +{ + svn::Pathes p; + for ( QValueListConstIterator<KURL> it = l.begin(); it != l.end() ; ++it ) { + p.append((*it).path()); + } + try { + m_pData->m_Svnclient->remove(svn::Targets(p),false); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + finished(); +} + +void kio_svnProtocol::wc_resolve(const KURL&url,bool recurse) +{ + try { + svn::Depth depth=recurse?svn::DepthInfinity:svn::DepthEmpty; + m_pData->m_Svnclient->resolve(url.path(),depth); + } catch (const svn::ClientException&e) { + error(KIO::ERR_SLAVE_DEFINED,e.msg()); + return; + } + finished(); +} + +void kio_svnProtocol::streamWritten(const KIO::filesize_t current) +{ + processedSize(current); +} + +void kio_svnProtocol::streamSendMime(KMimeMagicResult* mt) +{ + if (mt) { + mimeType(mt->mimeType()); + } +} + +void kio_svnProtocol::streamPushData(QByteArray array) +{ + data(array); +} + +void kio_svnProtocol::contextProgress(long long int current, long long int) +{ + if (m_pData->dispProgress) { + processedSize(current); + } +} + +void kio_svnProtocol::streamTotalSizeNull() +{ + totalSize(0); +} + + +/*! + \fn kio_svnProtocol::getDefaultLog() + */ +QString kio_svnProtocol::getDefaultLog() +{ + QString res = QString::null; + Kdesvnsettings::self()->readConfig(); + if (Kdesvnsettings::kio_use_standard_logmsg()) { + res = Kdesvnsettings::kio_standard_logmsg(); + } + return res; +} + +} // namespace KIO diff --git a/src/kiosvn/kiosvn.h b/src/kiosvn/kiosvn.h new file mode 100644 index 0000000..a3383e1 --- /dev/null +++ b/src/kiosvn/kiosvn.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KIOSVN_H +#define KIOSVN_H + +#include "kiobytestream.h" + +#include <qstring.h> +#include <qcstring.h> +#include <kurl.h> + +#include <kio/global.h> +#include <kio/slavebase.h> + + +#include <sys/stat.h> +#include <qvaluelist.h> + +namespace KIO +{ + +class KioSvnData; + +/** +@author Rajko Albrecht +*/ +class kio_svnProtocol : public KIO::SlaveBase,public StreamWrittenCb +{ +public: + kio_svnProtocol(const QCString &pool_socket, const QCString &app_socket); + virtual ~kio_svnProtocol(); + virtual void listDir (const KURL&url); + virtual void stat(const KURL& url); + virtual void get(const KURL& url); + virtual void mkdir (const KURL &url, int permissions); + virtual void mkdir (const KURL::List &urls, int permissions); + virtual void rename(const KURL&src,const KURL&target,bool force); + virtual void del(const KURL&url,bool isfile); + virtual void copy(const KURL&src,const KURL&dest,int permissions,bool overwrite); + virtual void checkout(const KURL&src,const KURL&target,const int rev, const QString&revstring); + virtual void svnlog(int,const QString&,int, const QString&, const KURL::List&); + virtual void revert(const KURL::List&); + virtual void wc_switch(const KURL&,const KURL&,bool,int,const QString&); + virtual void diff(const KURL&,const KURL&,int,const QString&,int, const QString&,bool); + virtual void import( const KURL& repos, const KURL& wc); + virtual void add(const KURL& wc); + virtual void wc_delete(const KURL::List&); + virtual void special(const QByteArray& data); + virtual void wc_resolve(const KURL&,bool); + /* looked on kio::svn from kdesdk */ + enum KSVN_METHOD { + /* KURL repository, KURL target, int revnumber, QString revkind */ + SVN_CHECKOUT = 1, + /* KURL wc, int revnumber, QString revkind */ + /* refkind may empty or HEAD or START, will get parsed if revnumber is -1 */ + SVN_UPDATE = 2, + /* KURL::List */ + SVN_COMMIT = 3, + /* int revstart, QString revstartstring, int revend, QString revendstring, KURL::List */ + SVN_LOG=4, + SVN_IMPORT=5, + /* KURL */ + SVN_ADD=6, + /*KURL::List */ + SVN_DEL=7, + /* KURL::List */ + SVN_REVERT=8, + /* KURL wc,bool checkRepos, bool recurse */ + SVN_STATUS=9, + /* KURL::List */ + SVN_MKDIR=10, + /* KURL, bool */ + SVN_RESOLVE=11, + /* KURL working copy, KURL new_repository_url, bool recurse, int rev, QString revstring */ + SVN_SWITCH=12, + /* KURL uri1, KURL uri2, int r1, QString rstring1, int r2, QString rstring 2, bool recursive */ + SVN_DIFF=13 + }; + + void contextProgress(long long int current, long long int max); + virtual void streamWritten(const KIO::filesize_t current); + virtual void streamPushData(QByteArray); + virtual void streamSendMime(KMimeMagicResult*mt); + virtual void streamTotalSizeNull(); + +protected: + virtual void commit(const KURL::List&); + virtual void status(const KURL&,bool,bool); + virtual void update(const KURL&,int,const QString&); + +private: + KioSvnData*m_pData; + bool createUDSEntry( const QString& filename, const QString& user, long long int size, bool isdir, time_t mtime, KIO::UDSEntry& entry); + QString makeSvnUrl(const KURL&url,bool check_wc=true); + bool checkWc(const KURL&url); + bool getLogMsg(QString&); +protected: + QString getDefaultLog(); +}; + +} + +#endif diff --git a/src/kiosvn/ksvn+file.protocol b/src/kiosvn/ksvn+file.protocol new file mode 100644 index 0000000..27edbef --- /dev/null +++ b/src/kiosvn/ksvn+file.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=ksvn+file +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/ksvn+http.protocol b/src/kiosvn/ksvn+http.protocol new file mode 100644 index 0000000..e16c353 --- /dev/null +++ b/src/kiosvn/ksvn+http.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=ksvn+http +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/ksvn+https.protocol b/src/kiosvn/ksvn+https.protocol new file mode 100644 index 0000000..fa828eb --- /dev/null +++ b/src/kiosvn/ksvn+https.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=ksvn+https +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/ksvn+ssh.protocol b/src/kiosvn/ksvn+ssh.protocol new file mode 100644 index 0000000..891abc9 --- /dev/null +++ b/src/kiosvn/ksvn+ssh.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=ksvn+ssh +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/ksvn.protocol b/src/kiosvn/ksvn.protocol new file mode 100644 index 0000000..7b2cc54 --- /dev/null +++ b/src/kiosvn/ksvn.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=ksvn +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/svn+file.protocol b/src/kiosvn/svn+file.protocol new file mode 100644 index 0000000..9b0a4fd --- /dev/null +++ b/src/kiosvn/svn+file.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=svn+file +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/svn+http.protocol b/src/kiosvn/svn+http.protocol new file mode 100644 index 0000000..6be6943 --- /dev/null +++ b/src/kiosvn/svn+http.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=svn+http +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/svn+https.protocol b/src/kiosvn/svn+https.protocol new file mode 100644 index 0000000..fc23bdc --- /dev/null +++ b/src/kiosvn/svn+https.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=svn+https +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/svn+ssh.protocol b/src/kiosvn/svn+ssh.protocol new file mode 100644 index 0000000..1c261b8 --- /dev/null +++ b/src/kiosvn/svn+ssh.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=svn+ssh +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/kiosvn/svn.protocol b/src/kiosvn/svn.protocol new file mode 100644 index 0000000..02226f2 --- /dev/null +++ b/src/kiosvn/svn.protocol @@ -0,0 +1,39 @@ +[Protocol] +exec=kio_ksvn +protocol=svn +input=none +output=filesystem +reading=true +writing=true +deleting=true +makedir=true +linking=false +moving=true +deleteRecursive=true +listing=Name,Size,Date,Owner +defaultMimetype=application/octet-stream +Icon=remote +Description=Subversion ioslave +Description[br]=Sklav E/D Subversion +Description[ca]=Ioslave de Subversion +Description[cs]=Subversion protokol +Description[de]=Ein-/Ausgabemodul für Subversion +Description[es]=El ioslave de Subversion +Description[et]=Subversioni IO-moodul +Description[fr]=ioslave subversion +Description[ga]=ioslave Subversion +Description[hu]=Subversion KDE-protokoll +Description[it]=Slave I/O di Subversion +Description[pl]=Wtyczka protokołu Subversion +Description[pt]='Ioslave' para Subversion +Description[pt_BR]=ioslave de Subversão +Description[ru]=Доступ к хранилищу Subversion +Description[sl]=ioslave za Subversion +Description[sr]=IOSlave за Subversion +Description[sr@Latn]=IOSlave za Subversion +Description[sv]=Subversion I/O-slav +Description[tr]=Alt Version ioslave +Description[uk]=Підлеглий В/В Subversion +Description[xx]=xxSubversion ioslavexx +maxInstances=5 +class=:internet diff --git a/src/ksvnwidgets/CMakeLists.txt b/src/ksvnwidgets/CMakeLists.txt new file mode 100644 index 0000000..2446aa1 --- /dev/null +++ b/src/ksvnwidgets/CMakeLists.txt @@ -0,0 +1,46 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/src/svnqt) + +KDE3_ADD_UI_FILES( + kdesvn_shared_ui + logmessage.ui + ssltrustprompt.ui + authdlg.ui + encodingselector.ui + depthform.ui + revertform.ui +) + +SET(ksvnwidgetsrc + authdialogimpl.cpp + logmsg_impl.cpp + ssltrustprompt_impl.cpp + pwstorage.cpp + diffbrowser.cpp + diffbrowserdata.cpp + diffsyntax.cpp + encodingselector_impl.cpp + depthselector.cpp + revertform_impl.cpp + ) + +SET(ksvnwidgethdr + authdialogimpl.h + logmsg_impl.h + ssltrustprompt_impl.h + pwstorage.h + diffbrowser.h + diffbrowserdata.h + diffsyntax.h + encodingselector_impl.h + depthselector.h + revertform_impl.h +) + +KDE3_AUTOMOC(${ksvnwidgetsrc}) + +ADD_LIBRARY(ksvnwidgets STATIC ${ksvnwidgetsrc} ${kdesvn_shared_ui} ${ksvnwidgethdr}) +SET_TARGET_PROPERTIES(ksvnwidgets + PROPERTIES + COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) + +ADD_DEPENDENCIES(ksvnwidgets kdesvncfgreader) diff --git a/src/ksvnwidgets/authdialogimpl.cpp b/src/ksvnwidgets/authdialogimpl.cpp new file mode 100644 index 0000000..5cd1fd5 --- /dev/null +++ b/src/ksvnwidgets/authdialogimpl.cpp @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "authdialogimpl.h" +#include "src/settings/kdesvnsettings.h" + +#include <kpassdlg.h> +#include <klineedit.h> +#include <klocale.h> +#include <qcheckbox.h> +#include <qlabel.h> + +AuthDialogImpl::AuthDialogImpl(const QString & realm,const QString&user,QWidget *parent, const char *name) + :AuthDialogData(parent, name),curPass("") +{ + m_UsernameEdit->setText(user); + m_PasswordEdit->setText(""); + m_StorePasswordButton->setChecked(Kdesvnsettings::store_passwords()); + QString text = m_StorePasswordButton->text(); + m_StorePasswordButton->setText( + m_StorePasswordButton->text()+QString(" (%1)") + .arg((Kdesvnsettings::passwords_in_wallet()?i18n("into KDE Wallet"):i18n("into subversions simple storage")))); + if (!realm.isEmpty()) { + m_RealmLabel->setText(m_RealmLabel->text()+" "+realm); + resize( QSize(334, 158).expandedTo(minimumSizeHint()) ); + } +} + +void AuthDialogImpl::slotHelp() +{ +} + +const QString AuthDialogImpl::Username()const +{ + return m_UsernameEdit->text(); +} + +const QString AuthDialogImpl::Password() +{ +#if 0 + /* as described in interface description wie must make a copy of string */ + curPass = QString::fromUtf8(m_PasswordEdit->password()); + return curPass; +#endif + return m_PasswordEdit->text(); +} + +bool AuthDialogImpl::maySave()const +{ + return m_StorePasswordButton->isChecked(); +} + +#include "authdialogimpl.moc" diff --git a/src/ksvnwidgets/authdialogimpl.h b/src/ksvnwidgets/authdialogimpl.h new file mode 100644 index 0000000..2f572b7 --- /dev/null +++ b/src/ksvnwidgets/authdialogimpl.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef AUTHDIALOGIMPL_H +#define AUTHDIALOGIMPL_H + +#include "src/ksvnwidgets/authdlg.h" +#include <qstring.h> + +class AuthDialogImpl: public AuthDialogData { +Q_OBJECT +public: + AuthDialogImpl(const QString & realm = "",const QString&user="", QWidget *parent = 0, const char *name = 0); + + const QString Username()const; + const QString Password(); + bool maySave()const; +protected slots: + virtual void slotHelp(); +protected: + QString curPass; +}; + +#endif diff --git a/src/ksvnwidgets/authdlg.ui b/src/ksvnwidgets/authdlg.ui new file mode 100644 index 0000000..764fd87 --- /dev/null +++ b/src/ksvnwidgets/authdlg.ui @@ -0,0 +1,195 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>AuthDialogData</class> +<widget class="QDialog"> + <property name="name"> + <cstring>AuthDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>418</width> + <height>158</height> + </rect> + </property> + <property name="caption"> + <string>Authentication</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_RealmLabel</cstring> + </property> + <property name="text"> + <string>Enter authentification info for</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_PasswordLabel</cstring> + </property> + <property name="text"> + <string>Password:</string> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>m_PasswordEdit</cstring> + </property> + <property name="echoMode"> + <enum>Password</enum> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>m_UsernameEdit</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_UsernameLabel</cstring> + </property> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_StorePasswordButton</cstring> + </property> + <property name="text"> + <string>Store password</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>OK</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>Cancel</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>90</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonHelp</cstring> + </property> + <property name="text"> + <string>Help</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>AuthDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>AuthDialog</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>buttonHelp</sender> + <signal>clicked()</signal> + <receiver>AuthDialog</receiver> + <slot>slotHelp()</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_UsernameEdit</tabstop> + <tabstop>m_PasswordEdit</tabstop> + <tabstop>m_StorePasswordButton</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonCancel</tabstop> + <tabstop>buttonHelp</tabstop> +</tabstops> +<slots> + <slot access="protected">slotHelp()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/src/ksvnwidgets/depthform.ui b/src/ksvnwidgets/depthform.ui new file mode 100644 index 0000000..3a5d126 --- /dev/null +++ b/src/ksvnwidgets/depthform.ui @@ -0,0 +1,93 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DepthSettings</class> +<comment>Selector widget for depth enumeration</comment> +<author>Rajko Albrecht</author> +<widget class="QWidget"> + <property name="name"> + <cstring>DepthForm</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>209</width> + <height>46</height> + </rect> + </property> + <property name="caption"> + <string>Form1</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Empty Depth</string> + </property> + </item> + <item> + <property name="text"> + <string>Files Depth</string> + </property> + </item> + <item> + <property name="text"> + <string>Immediate Depth</string> + </property> + </item> + <item> + <property name="text"> + <string>Infinity Depth (recurse)</string> + </property> + </item> + <property name="name"> + <cstring>m_DepthCombo</cstring> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Select depth of operation</string> + </property> + <property name="whatsThis" stdset="0"> + <string><b>Kind of depth</b>: +<p> +<i>empty depth</i><br>Just the named directory, no entries. Updates will not pull in any files or subdirectories not already present. +</p> +<p> +<i>Files depth</i><br>Folder and its file children, but not subdirs. Updates will pull in any files not already present, but not subdirectories. +</p> +<p> +<i>Immediate depth</i><br> +Folder and its entries. Updates will pull in any files or subdirectories not already present; those subdirectories entries will have depth-empty. +</p> +<p> +<i>Infinity depth</i><br> +Updates will pull in any files or subdirectories not already present; those subdirectories' this_dir entries will have depth-infinity.<br> +Equivalent to the pre-1.5 default update behavior. +</p></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>m_leftspacer</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/ksvnwidgets/depthselector.cpp b/src/ksvnwidgets/depthselector.cpp new file mode 100644 index 0000000..842adcf --- /dev/null +++ b/src/ksvnwidgets/depthselector.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "depthselector.h" +#include "src/svnqt/version_check.hpp" + +#include <klocale.h> + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qlayout.h> +#include <qcombobox.h> + + +DepthSelector::DepthSelector(QWidget *parent, const char *name) + :DepthSettings(parent, name) +{ + if (svn::Version::version_major()>1|| svn::Version::version_minor()>4 ) { + m_recurse = 0L; + m_DepthCombo->setCurrentItem(3); + } else { + delete m_DepthCombo; + m_DepthCombo=0; + DepthFormLayout->removeItem(m_leftspacer); + m_recurse = new QCheckBox( this, "m_RecursiveButton" ); + m_recurse->setChecked( TRUE ); + m_recurse->setText(i18n( "Recursive" )); + DepthFormLayout->addWidget( m_recurse ); + m_recurse->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + DepthFormLayout->addItem(m_leftspacer); + } + DepthFormLayout->setMargin(0); + setMinimumSize(minimumSizeHint()); + adjustSize(); +} + +DepthSelector::~DepthSelector() +{ +} +void DepthSelector::addItemWidget(QWidget*aWidget) +{ + DepthFormLayout->removeItem(m_leftspacer); + aWidget->reparent(this,geometry().topLeft()); + DepthFormLayout->addWidget(aWidget); + aWidget->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + DepthFormLayout->addItem(m_leftspacer); + setMinimumSize(minimumSizeHint()); +} + +/*! + \fn DepthSelector::getDepth()const + */ +svn::Depth DepthSelector::getDepth()const +{ + if (m_DepthCombo) { + switch (m_DepthCombo->currentItem()){ + case 0: + return svn::DepthEmpty; + break; + case 1: + return svn::DepthFiles; + break; + case 2: + return svn::DepthImmediates; + break; + case 3: + default: + return svn::DepthInfinity; + } + } else { + return (m_recurse->isChecked()?svn::DepthInfinity:svn::DepthEmpty); + } +} + +void DepthSelector::hideDepth(bool hide) +{ + QWidget*w = m_DepthCombo? (QWidget*)m_DepthCombo:(QWidget*)m_recurse; + if (hide) w->hide(); else w->show(); +} + +#include "depthselector.moc" diff --git a/src/ksvnwidgets/depthselector.h b/src/ksvnwidgets/depthselector.h new file mode 100644 index 0000000..649537b --- /dev/null +++ b/src/ksvnwidgets/depthselector.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DEPTHSELECTOR_H +#define DEPTHSELECTOR_H + +#include "src/ksvnwidgets/depthform.h" + +#include "src/svnqt/svnqttypes.hpp" + +class QCheckBox; + +class DepthSelector: public DepthSettings { + Q_OBJECT +public: + DepthSelector(QWidget *parent = 0, const char *name = 0); + virtual ~DepthSelector(); + svn::Depth getDepth()const; + void addItemWidget(QWidget*); + void hideDepth(bool hide); + +protected: + QCheckBox*m_recurse; +}; + +#endif diff --git a/src/ksvnwidgets/diffbrowser.cpp b/src/ksvnwidgets/diffbrowser.cpp new file mode 100644 index 0000000..d1f7b6f --- /dev/null +++ b/src/ksvnwidgets/diffbrowser.cpp @@ -0,0 +1,256 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "diffbrowser.h" +#include "diffbrowserdata.h" +#include "src/settings/kdesvnsettings.h" + +#include <kglobalsettings.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <klocale.h> + +#include <qfont.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qtextcodec.h> + +/*! + \fn DiffBrowser::DiffBrowser(QWidget*parent=0,const char*name=0) + */ +DiffBrowser::DiffBrowser(QWidget*parent,const char*name) + : KTextBrowser( parent, name) +{ + setTextFormat(Qt::PlainText); + setFont(KGlobalSettings::fixedFont()); + m_Data = new DiffBrowserData; + + setWordWrap(QTextEdit::NoWrap); + m_Data->m_Syntax = new DiffSyntax(this); + QToolTip::add(this,i18n("Ctrl-F for search, F3 or Shift-F3 for search again.")); + QWhatsThis::add(this,i18n("<b>Display differences between files</b><p>You may search inside text with Ctrl-F.</p><p>F3 for search forward again, Shift-F3 for search backward again.</p><p>You may save the (original) output with Ctrl-S.</p>")); + setFocus(); +} + +/*! + \fn DiffBrowser::~DiffBrowser() + */ + DiffBrowser::~DiffBrowser() +{ + delete m_Data; +} + +void DiffBrowser::setText(const QString&aText) +{ + m_Data->m_content.setRawData(aText.local8Bit(),aText.local8Bit().size()); + KTextBrowser::setText(aText); + setCursorPosition(0,0); +} + +void DiffBrowser::setText(const QByteArray&aText) +{ + m_Data->m_content=aText; + printContent(); + setCursorPosition(0,0); +} + +void DiffBrowser::printContent() +{ + QTextCodec * cc = QTextCodec::codecForName(Kdesvnsettings::locale_for_diff()); + if (!cc) { + KTextBrowser::setText(QString::fromLocal8Bit(m_Data->m_content,m_Data->m_content.size())); + } else { + KTextBrowser::setText(cc->toUnicode(m_Data->m_content,m_Data->m_content.size())); + } +} + +/*! + \fn DiffBrowser::saveDiff() + */ +void DiffBrowser::saveDiff() +{ + QString saveTo = KFileDialog::getSaveFileName(QString::null,"text/x-diff"); + if (saveTo.isEmpty()) { + return; + } + QFile tfile(saveTo); + if (tfile.exists()) { + if (KMessageBox::warningYesNo(KApplication::activeModalWidget(), + i18n("File %1 exists - overwrite?").arg(saveTo)) + !=KMessageBox::Yes) { + return; + } + } + tfile.open(IO_Truncate|IO_WriteOnly|IO_Raw); + QDataStream stream( &tfile ); + stream.writeRawBytes(m_Data->m_content.data(),m_Data->m_content.size()); +} + +void DiffBrowser::keyPressEvent(QKeyEvent*ev) +{ + if ( ev->key() == Key_Return) { + ev->ignore(); + return; + } + if (ev->key() == Key_F3) { + if (ev->state() == ShiftButton) { + searchagainback_slot(); + } else { + searchagain_slot(); + } + } else if (ev->key()==Key_F && ev->state() == ControlButton) { + startSearch(); + } else if (ev->key()==Key_S && ev->state() == ControlButton) { + saveDiff(); + } else { + KTextBrowser::keyPressEvent(ev); + } +} + +void DiffBrowser::startSearch() +{ + if( !m_Data->srchdialog ) { + m_Data->srchdialog = new KEdFind( this, "searchdialog", false); + connect(m_Data->srchdialog,SIGNAL(search()),this,SLOT(search_slot())); + connect(m_Data->srchdialog,SIGNAL(done()),this,SLOT(searchdone_slot())); + } + QString _st = m_Data->srchdialog->getText(); + m_Data->srchdialog->setText(_st.isEmpty() ? m_Data->pattern : _st); + m_Data->srchdialog->show(); + m_Data->srchdialog->result(); +} + +/*! + \fn DiffBrowser::search_slot() + */ +void DiffBrowser::search_slot() +{ + if( !m_Data->srchdialog ) { + return; + } + QString to_find_string = m_Data->srchdialog->getText(); + doSearch(to_find_string,m_Data->srchdialog->case_sensitive(),m_Data->srchdialog->get_direction()); +} + +void DiffBrowser::doSearch(const QString&to_find_string,bool case_sensitive,bool back) +{ + if( !m_Data->srchdialog ) { + return; + } + int line, col; + getCursorPosition(&line,&col); + if (m_Data->last_search != DiffBrowserData::NONE && !back) { + col = col+1; + } + while (1) { + bool result = find(to_find_string,case_sensitive,false, + (!back),&line,&col); + + if (result) { + m_Data->last_search = back?DiffBrowserData::BACKWARD:DiffBrowserData::FORWARD; + m_Data->pattern=to_find_string; + break; + } + QWidget * _parent = m_Data->srchdialog->isVisible()?m_Data->srchdialog:parentWidget(); + if (!m_Data->srchdialog->get_direction()) { + // forward + int query = KMessageBox::questionYesNo( + _parent, + i18n("End of document reached.\n"\ + "Continue from the beginning?"), + i18n("Find"),KStdGuiItem::cont(),i18n("Stop")); + if (query == KMessageBox::Yes){ + line = 0; + col = 0; + m_Data->last_search = DiffBrowserData::FORWARD; + } else { + break; + } + } else { + int query = KMessageBox::questionYesNo( + _parent, + i18n("Beginning of document reached.\n"\ + "Continue from the end?"), + i18n("Find"),KStdGuiItem::cont(),i18n("Stop")); + if (query == KMessageBox::Yes){ + line = lines()-1; + QString string = text(line); + col = string.length(); + if (col>0) { + --col; + } + m_Data->last_search = DiffBrowserData::BACKWARD; + } else { + break; + } + } + } +} + +/*! + \fn DiffBrowser::searchdone_slot() + */ +void DiffBrowser::searchdone_slot() +{ + if (!m_Data->srchdialog) + return; + + m_Data->srchdialog->hide(); + setFocus(); + m_Data->last_finished_search = m_Data->last_search; + m_Data->last_search = DiffBrowserData::NONE; + m_Data->cs = m_Data->srchdialog->case_sensitive(); +} + +void DiffBrowser::searchagain_slot() +{ + doSearchAgain(false); +} + +void DiffBrowser::searchagainback_slot() +{ + doSearchAgain(true); +} + +void DiffBrowser::doSearchAgain(bool back) +{ + if (!m_Data->srchdialog || m_Data->pattern.isEmpty()) { + startSearch(); + } else { + m_Data->last_search = m_Data->last_finished_search; + doSearch(m_Data->pattern,m_Data->cs,back); + m_Data->last_finished_search = m_Data->last_search; + m_Data->last_search = DiffBrowserData::NONE; + } +} + +void DiffBrowser::slotTextCodecChanged(const QString&codec) +{ + if (Kdesvnsettings::locale_for_diff()!=codec) { + Kdesvnsettings::setLocale_for_diff(codec); + printContent(); + Kdesvnsettings::self()->writeConfig(); + } +} + +#include "diffbrowser.h.moc" diff --git a/src/ksvnwidgets/diffbrowser.h b/src/ksvnwidgets/diffbrowser.h new file mode 100644 index 0000000..f7aa946 --- /dev/null +++ b/src/ksvnwidgets/diffbrowser.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _DIFF_BROWSER_H +#define _DIFF_BROWSER_H + +#include <ktextbrowser.h> + +class DiffSyntax; +class KEdFind; + +class DiffBrowserData; + +class DiffBrowser : public KTextBrowser +{ + Q_OBJECT + +public: + DiffBrowser(QWidget*parent=0,const char*name=0); + virtual ~DiffBrowser(); + +public slots: + virtual void setText(const QString&aText); + virtual void setText(const QByteArray&ex); + virtual void saveDiff(); + virtual void slotTextCodecChanged(const QString&); + +protected: + virtual void keyPressEvent(QKeyEvent*); + + virtual void startSearch(); + virtual void doSearch(const QString&to_find_string,bool case_sensitive,bool back); + virtual void doSearchAgain(bool back); + +protected: + DiffBrowserData*m_Data; + + void printContent(); + +protected slots: + virtual void search_slot(); + virtual void searchdone_slot(); + virtual void searchagain_slot(); + virtual void searchagainback_slot(); +}; + +#endif + diff --git a/src/ksvnwidgets/diffbrowserdata.cpp b/src/ksvnwidgets/diffbrowserdata.cpp new file mode 100644 index 0000000..5eac74a --- /dev/null +++ b/src/ksvnwidgets/diffbrowserdata.cpp @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "diffbrowserdata.h" + +/*! + \fn DiffBrowserData::DiffBrowserData() + */ + DiffBrowserData::DiffBrowserData() +{ + m_Syntax=0; + srchdialog=0; + last_search = NONE; + last_finished_search = NONE; + cs = false; +} + + +/*! + \fn DiffBrowserData::~DiffBrowserData() + */ + DiffBrowserData::~DiffBrowserData() +{ + delete m_Syntax; + delete srchdialog; +} diff --git a/src/ksvnwidgets/diffbrowserdata.h b/src/ksvnwidgets/diffbrowserdata.h new file mode 100644 index 0000000..13ab161 --- /dev/null +++ b/src/ksvnwidgets/diffbrowserdata.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "diffsyntax.h" + +#include <keditcl.h> + +#include <qstring.h> + +class DiffBrowserData +{ +public: + DiffBrowserData(); + virtual ~DiffBrowserData(); + + enum {NONE, FORWARD, BACKWARD}; + + DiffSyntax*m_Syntax; + QByteArray m_content; + KEdFind *srchdialog; + + int last_search,last_finished_search; + QString pattern; + bool cs; +}; diff --git a/src/ksvnwidgets/diffsyntax.cpp b/src/ksvnwidgets/diffsyntax.cpp new file mode 100644 index 0000000..a38c749 --- /dev/null +++ b/src/ksvnwidgets/diffsyntax.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "diffsyntax.h" +#include <kglobalsettings.h> +#include <kglobal.h> +#include <kdebug.h> + +#include <qregexp.h> + +/*! + \fn DiffSyntax::DiffSyntax(QTextEdit*) + */ + DiffSyntax::DiffSyntax(QTextEdit*aTextEdit) + : QSyntaxHighlighter(aTextEdit) +{ +} + + +/*! + \fn DiffSyntax::highlightParagraph ( const QString & text, int endStateOfLastPara ) + */ +int DiffSyntax::highlightParagraph ( const QString & aText, int endStateOfLastPara) +{ + static QRegExp a("^\\w+:\\s.*$"); + static QRegExp b("^\\W+$"); + QColor c(0,0,0); + QFont f(KGlobalSettings::fixedFont()); + int ret = 0; + if (endStateOfLastPara == 1) { + ret = 2; + } else if (endStateOfLastPara == 2) { + if (b.match(aText)!=0) { + ret = 2; + } + } + + if (a.match(aText)>-1) { + c = QColor("#660033"); + if (endStateOfLastPara==1||endStateOfLastPara==2) { + f.setBold(true); + } else { + f.setItalic(true); + } + } else if (aText.startsWith("_____" )) { + ret = 1; + c = QColor("#1D1D8F"); + } else if (aText.startsWith("+")) { + c = QColor("#008B00"); + if (aText.startsWith("+++")) { + f.setBold(true); + } + } else if (aText.startsWith("-")) { + c = QColor("#CD3333"); + if (aText.startsWith("---")) { + f.setBold(true); + } + } else if (aText.startsWith("@@")) { + c = QColor("#1D1D8F"); + } + if (endStateOfLastPara==2 && ret==2) { + if (aText.startsWith(" +")) { + c = QColor("#008B00"); + } else if (aText.startsWith(" -")) { + c = QColor("#CD3333"); + } + } + setFormat(0,(int)aText.length(),f,c); + return ret; +} + + +/*! + \fn DiffSyntax::~DiffSyntax() + */ + DiffSyntax::~DiffSyntax() +{ +} diff --git a/src/ksvnwidgets/diffsyntax.h b/src/ksvnwidgets/diffsyntax.h new file mode 100644 index 0000000..1c1f779 --- /dev/null +++ b/src/ksvnwidgets/diffsyntax.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _DIFFSYNTAX_H +#define _DIFFSYNTAX_H + +#include <qsyntaxhighlighter.h> +#include <qregexp.h> +#include <qfont.h> + +class QTextEdit; +class QString; +class QColor; + +class DiffSyntax : public QSyntaxHighlighter +{ +public: + DiffSyntax(QTextEdit*); + virtual int highlightParagraph ( const QString & text, int endStateOfLastPara ); + virtual ~DiffSyntax(); +}; + +#endif + diff --git a/src/ksvnwidgets/encodingselector.ui b/src/ksvnwidgets/encodingselector.ui new file mode 100644 index 0000000..8ea58fb --- /dev/null +++ b/src/ksvnwidgets/encodingselector.ui @@ -0,0 +1,91 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>EncodingSelector</class> +<author>Rajko Albrecht</author> +<widget class="QWidget"> + <property name="name"> + <cstring>EncodingSelector</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>202</width> + <height>24</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Form1</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_Mainlabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Select encoding:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Default utf-8</string> + </property> + </item> + <property name="name"> + <cstring>m_encodingList</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </hbox> +</widget> +<connections> + <connection> + <sender>m_encodingList</sender> + <signal>activated(int)</signal> + <receiver>EncodingSelector</receiver> + <slot>itemActivated(int)</slot> + </connection> +</connections> +<slots> + <slot access="protected">itemActivated(int)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/ksvnwidgets/encodingselector_impl.cpp b/src/ksvnwidgets/encodingselector_impl.cpp new file mode 100644 index 0000000..d062970 --- /dev/null +++ b/src/ksvnwidgets/encodingselector_impl.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "encodingselector_impl.h" +#include <kdebug.h> +#include <kcharsets.h> +#include <kglobal.h> + +#include <qcombobox.h> + +EncodingSelector_impl::EncodingSelector_impl(const QString&cur,QWidget *parent, const char *name) + :EncodingSelector(parent, name) +{ + m_encodingList->insertStringList( KGlobal::charsets()->availableEncodingNames()); + + for (int j = 1;j<m_encodingList->count();++j ) { + if(m_encodingList->text(j)==cur) { + m_encodingList->setCurrentItem(j); + break; + } + } +} + +void EncodingSelector_impl::itemActivated(int which) +{ + if (which == 0) { + emit TextCodecChanged(QString("")); + } else { + emit TextCodecChanged(m_encodingList->currentText()); + } +} + +#include "encodingselector_impl.moc" + diff --git a/src/ksvnwidgets/encodingselector_impl.h b/src/ksvnwidgets/encodingselector_impl.h new file mode 100644 index 0000000..ff8f8e6 --- /dev/null +++ b/src/ksvnwidgets/encodingselector_impl.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef LOCALESELECTOR_IMPL_H +#define LOCALESELECTOR_IMPL_H + +#include "src/ksvnwidgets/encodingselector.h" + +class QTextCodec; + +class EncodingSelector_impl: public EncodingSelector { +Q_OBJECT +public: + EncodingSelector_impl(const QString&cur, QWidget *parent = 0, const char *name = 0); + virtual ~EncodingSelector_impl(){} + +protected slots: + virtual void itemActivated(int); + +signals: + void TextCodecChanged(const QString&); +}; + +#endif diff --git a/src/ksvnwidgets/logmessage.ui b/src/ksvnwidgets/logmessage.ui new file mode 100644 index 0000000..faa8bd9 --- /dev/null +++ b/src/ksvnwidgets/logmessage.ui @@ -0,0 +1,344 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>LogmessageData</class> +<widget class="QWidget"> + <property name="name"> + <cstring>LogmessageData</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>584</width> + <height>368</height> + </rect> + </property> + <property name="caption"> + <string>Logmessage</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSplitter"> + <property name="name"> + <cstring>m_MainSplitter</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>m_ReviewFrame</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_Reviewlabel</cstring> + </property> + <property name="text"> + <string>Review affected items</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QListView"> + <column> + <property name="text"> + <string>Entry</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Action</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_ReviewList</cstring> + </property> + <property name="resizePolicy"> + <enum>Manual</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="showSortIndicator"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_HideNewItems</cstring> + </property> + <property name="text"> + <string>Hide new items</string> + </property> + <property name="toggleButton"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_MarkUnversioned</cstring> + </property> + <property name="text"> + <string>Select new items</string> + </property> + <property name="toolTip" stdset="0"> + <string>Mark all new e.g. not versioned items for add and commit.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_UnmarkUnversioned</cstring> + </property> + <property name="text"> + <string>Unselect new items</string> + </property> + <property name="toolTip" stdset="0"> + <string>Unmark all unversioned items so they will be ignored.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_DiffItem</cstring> + </property> + <property name="text"> + <string>Diff highlighted item</string> + </property> + <property name="toolTip" stdset="0"> + <string>Generates and display difference against repository of selected item</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>m_EditFrame</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_HeadLabel</cstring> + </property> + <property name="text"> + <string>Enter a log message</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="KTextEdit"> + <property name="name"> + <cstring>m_LogEdit</cstring> + </property> + </widget> + </vbox> + </widget> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KComboBox" row="1" column="0"> + <item> + <property name="text"> + <string></string> + </property> + </item> + <property name="name"> + <cstring>m_LogHistory</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>2</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Last used log messages</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_LogLabel</cstring> + </property> + <property name="text"> + <string>Or insert one of the last:</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_insert_file_button</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Insert Textfile</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>m_ItemsLayout</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="DepthSelector"> + <property name="name"> + <cstring>m_DepthSelector</cstring> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_keepLocksButton</cstring> + </property> + <property name="text"> + <string>Keep locks</string> + </property> + <property name="toolTip" stdset="0"> + <string>If checked commit will not release locks.</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>DepthSelector</class> + <header location="local">src/ksvnwidgets/depthselector.h</header> + <sizehint> + <width>-1</width> + <height>30</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>m_LogHistory</sender> + <signal>activated(int)</signal> + <receiver>LogmessageData</receiver> + <slot>slotHistoryActivated(int)</slot> + </connection> + <connection> + <sender>m_MarkUnversioned</sender> + <signal>clicked()</signal> + <receiver>LogmessageData</receiver> + <slot>slotMarkUnversioned()</slot> + </connection> + <connection> + <sender>m_UnmarkUnversioned</sender> + <signal>clicked()</signal> + <receiver>LogmessageData</receiver> + <slot>slotUnmarkUnversioned()</slot> + </connection> + <connection> + <sender>m_DiffItem</sender> + <signal>clicked()</signal> + <receiver>LogmessageData</receiver> + <slot>slotDiffSelected()</slot> + </connection> + <connection> + <sender>m_HideNewItems</sender> + <signal>toggled(bool)</signal> + <receiver>LogmessageData</receiver> + <slot>hideNewItems(bool)</slot> + </connection> + <connection> + <sender>m_insert_file_button</sender> + <signal>clicked()</signal> + <receiver>LogmessageData</receiver> + <slot>insertFile()</slot> + </connection> +</connections> +<slots> + <slot access="protected">slotHistoryActivated(const QString&)</slot> + <slot access="protected">slotHistoryActivated(int)</slot> + <slot access="protected">slotMarkUnversioned()</slot> + <slot access="protected">slotDiffSelected()</slot> + <slot access="protected">slotUnmarkUnversioned()</slot> + <slot access="protected">hideNewItems(bool)</slot> + <slot access="protected">insertFile()</slot> +</slots> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>ktextedit.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>src/ksvnwidgets/depthselector.h</includehint> +</includehints> +</UI> diff --git a/src/ksvnwidgets/logmsg_impl.cpp b/src/ksvnwidgets/logmsg_impl.cpp new file mode 100644 index 0000000..f083d4c --- /dev/null +++ b/src/ksvnwidgets/logmsg_impl.cpp @@ -0,0 +1,653 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "logmsg_impl.h" +#include "src/settings/kdesvnsettings.h" +#include "depthselector.h" + +#include <ktextedit.h> +#include <kcombobox.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kapp.h> +#include <kconfigbase.h> +#include <kconfig.h> +#include <kurlrequesterdlg.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#include <kfile.h> +#include <kurlrequester.h> + +#include <qvbox.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlistview.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qpushbutton.h> +#include <qfile.h> + +#define MAX_MESSAGE_HISTORY 10 + +QValueList<QString> Logmsg_impl::sLogHistory = QValueList<QString>(); +QString Logmsg_impl::sLastMessage=QString(); +const QString Logmsg_impl::groupName("logmsg_dlg_size"); + +unsigned int Logmsg_impl::smax_message_history = 0xFFFF; + +class SvnCheckListItem:public QCheckListItem +{ +protected: + Logmsg_impl::logActionEntry m_Content; +public: + SvnCheckListItem(QListView*,const Logmsg_impl::logActionEntry&); + const Logmsg_impl::logActionEntry&data(){return m_Content;} + virtual int rtti()const{return 1000;} + virtual int compare( QListViewItem* item, int col, bool ascending ) const; +}; + +Logmsg_impl::Logmsg_impl(QWidget *parent, const char *name) + :LogmessageData(parent, name) +{ + m_LogEdit->setFocus(); + m_Reviewlabel->hide(); + m_ReviewList->hide(); + m_hidden=true; + hideButtons(true); + m_MainSplitter->moveToFirst(m_EditFrame); + delete m_ReviewFrame; + m_Reviewlabel=0; + m_ReviewList=0; + m_MarkUnversioned=0; + m_UnmarkUnversioned=0; + m_DiffItem=0; +} + +Logmsg_impl::Logmsg_impl(const svn::CommitItemList&_items,QWidget *parent, const char *name) + :LogmessageData(parent, name) +{ + m_LogEdit->setFocus(); + m_ReviewList->setColumnText(1,i18n("Items to commit")); + m_ReviewList->setColumnText(0,i18n("Action")); + m_ReviewList->setSortColumn(1); + hideButtons(true); + if (_items.count()>0) { + for (unsigned i = 0;i<_items.count();++i) { + QListViewItem*item = new QListViewItem(m_ReviewList); + if (_items[i].path().isEmpty()) { + item->setText(1,_items[i].url()); + } else { + item->setText(1,_items[i].path()); + } + item->setText(0,QChar(_items[i].actionType())); + } + m_hidden=false; + } else { + m_Reviewlabel->hide(); + m_ReviewList->hide(); + m_hidden=true; + } + checkSplitterSize(); +} + +Logmsg_impl::Logmsg_impl(const QMap<QString,QString>&_items,QWidget *parent, const char *name) + :LogmessageData(parent, name) +{ + m_LogEdit->setFocus(); + m_ReviewList->setColumnText(1,i18n("Items to commit")); + m_ReviewList->setColumnText(0,i18n("Action")); + m_ReviewList->setSortColumn(1); + hideButtons(true); + if (_items.count()>0) { + QMap<QString,QString>::ConstIterator it = _items.begin(); + for (;it!=_items.end();++it) { + QListViewItem*item = new QListViewItem(m_ReviewList); + item->setText(1,it.key()); + item->setText(0,it.data()); + } + m_hidden=false; + } else { + m_Reviewlabel->hide(); + m_ReviewList->hide(); + m_hidden=true; + } + checkSplitterSize(); +} + +Logmsg_impl::Logmsg_impl(const logActionEntries&_activatedList, + const logActionEntries&_notActivatedList, + QWidget *parent, const char *name) + :LogmessageData(parent, name) +{ + m_LogEdit->setFocus(); + m_hidden=false; + for (unsigned j = 0; j<_activatedList.count();++j) { + SvnCheckListItem * item = new SvnCheckListItem(m_ReviewList,_activatedList[j]); + item->setState(QCheckListItem::On); + } + for (unsigned j = 0; j<_notActivatedList.count();++j) { + SvnCheckListItem * item = new SvnCheckListItem(m_ReviewList,_notActivatedList[j]); + item->setState(QCheckListItem::Off); + } + m_HideNewItems->setOn(Kdesvnsettings::commit_hide_new()); + checkSplitterSize(); +} + +Logmsg_impl::~Logmsg_impl() +{ + QValueList<int> list = m_MainSplitter->sizes(); + if (!m_hidden && list.count()==2) { + Kdesvnsettings::setCommit_splitter_height(list); + Kdesvnsettings::writeConfig(); + } + for (unsigned int j=0; j<m_Hidden.size();++j) { + delete m_Hidden[j]; + } + Kdesvnsettings::setCommit_hide_new(m_HideNewItems->state()==QButton::On); +} + +void Logmsg_impl::checkSplitterSize() +{ + QValueList<int> list = Kdesvnsettings::commit_splitter_height(); + if (list.count()!=2) { + return; + } + if (m_hidden) { + list[1]=list[0]+list[1]; + list[0]=0; + } + if (m_hidden || (list[0]>0||list[1]>0)) { + m_MainSplitter->setSizes(list); + } +} + +void Logmsg_impl::slotHistoryActivated(int number) +{ + if (number < 1||(unsigned)number>sLogHistory.size()) { + m_LogEdit->setText(""); + } else { + m_LogEdit->setText(sLogHistory[number-1]); + } +} + +/*! + \fn Logmsg_impl::getMessage()const + */ +QString Logmsg_impl::getMessage()const +{ + return m_LogEdit->text(); +} + + +/*! + \fn Logmsg_impl::isRecursive()const + */ +svn::Depth Logmsg_impl::getDepth()const +{ + return m_DepthSelector->getDepth(); +} + +/*! + \fn Logmsg_impl::isRecursive()const + */ +bool Logmsg_impl::isKeeplocks()const +{ + return m_keepLocksButton->isChecked(); +} + + +/*! + \fn Logmsg_impl::initHistory() + */ +void Logmsg_impl::initHistory() +{ + if (smax_message_history==0xFFFF) { + smax_message_history = Kdesvnsettings::max_log_messages(); + KConfigGroup cs(Kdesvnsettings::self()->config(),"log_messages"); + QString s = QString::null; + unsigned int current = 0; + QString key = QString("log_%0").arg(current); + s = cs.readEntry(key,QString::null); + while (s!=QString::null) { + if (current<smax_message_history) { + sLogHistory.push_back(s); + } else { + cs.deleteEntry(key); + } + ++current; + key = QString("log_%0").arg(current); + s = cs.readEntry(key,QString::null); + } + } + QValueList<QString>::const_iterator it; + for (it=sLogHistory.begin();it!=sLogHistory.end();++it) { + if ((*it).length()<=40) { + m_LogHistory->insertItem((*it)); + } else { + m_LogHistory->insertItem((*it).left(37)+"..."); + } + } + if (sLastMessage.length()>0) { + m_LogEdit->setText(sLastMessage); + sLastMessage=QString(); + } +} + + +/*! + \fn Logmsg_impl::saveHistory() + */ +void Logmsg_impl::saveHistory(bool canceld) +{ + if (m_LogEdit->text().length()==0||m_LogEdit->text().length()>512) return; + /// @todo make static threadsafe + if (!canceld) { + QValueList<QString>::iterator it; + if ( (it=sLogHistory.find(m_LogEdit->text()))!=sLogHistory.end()) { + sLogHistory.erase(it); + } + sLogHistory.push_front(m_LogEdit->text()); + if (sLogHistory.size()>smax_message_history) { + sLogHistory.erase(sLogHistory.fromLast()); + } + KConfigGroup cs(Kdesvnsettings::self()->config(),"log_messages"); + for (unsigned int i = 0; i < sLogHistory.size();++i) { + cs.writeEntry(QString("log_%0").arg(i),sLogHistory[i]); + } + cs.sync(); + } else { + sLastMessage=m_LogEdit->text(); + } +} + +QString Logmsg_impl::getLogmessage(bool*ok,svn::Depth*rec,bool*keep_locks,QWidget*parent,const char*name) +{ + bool _ok,_keep_locks; + svn::Depth _depth = svn::DepthUnknown; + QString msg(""); + + Logmsg_impl*ptr=0; + KDialogBase dlg(parent,name,true,i18n("Commit log"), + KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::Ok,true); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + + ptr = new Logmsg_impl(Dialog1Layout); + if (!rec) { + ptr->m_DepthSelector->hide(); + } + if (!keep_locks) { + ptr->m_keepLocksButton->hide(); + } + ptr->initHistory(); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),groupName)); + if (dlg.exec()!=QDialog::Accepted) { + _ok = false; + /* avoid compiler warnings */ + _keep_locks = false; + } else { + _ok = true; + _depth = ptr->getDepth(); + _keep_locks = ptr->isKeeplocks(); + msg=ptr->getMessage(); + } + ptr->saveHistory(!_ok); + + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),groupName,false); + if (ok) *ok = _ok; + if (rec) *rec = _depth; + return msg; +} + +QString Logmsg_impl::getLogmessage(const svn::CommitItemList&items,bool*ok,svn::Depth*rec,bool*keep_locks,QWidget*parent,const char*name) +{ + bool _ok,_keep_locks; + svn::Depth _depth = svn::DepthUnknown; + QString msg(""); + + Logmsg_impl*ptr=0; + KDialogBase dlg(parent,name,true,i18n("Commit log"), + KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::Ok,true); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + + ptr = new Logmsg_impl(items,Dialog1Layout); + if (!rec) { + ptr->m_DepthSelector->hide(); + } + if (!keep_locks) { + ptr->m_keepLocksButton->hide(); + } + + ptr->initHistory(); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),groupName)); + if (dlg.exec()!=QDialog::Accepted) { + _ok = false; + /* avoid compiler warnings */ + _keep_locks = false; + } else { + _ok = true; + _depth = ptr->getDepth(); + _keep_locks = ptr->isKeeplocks(); + msg=ptr->getMessage(); + } + ptr->saveHistory(!_ok); + + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),groupName,false); + if (ok) *ok = _ok; + if (rec) *rec = _depth; + if (keep_locks) *keep_locks = _keep_locks; + return msg; +} + +QString Logmsg_impl::getLogmessage(const QMap<QString,QString>&items, + bool*ok,svn::Depth*rec,bool*keep_locks,QWidget*parent,const char*name) +{ + bool _ok,_rec,_keep_locks; + svn::Depth _depth = svn::DepthUnknown; + QString msg(""); + + Logmsg_impl*ptr=0; + KDialogBase dlg(parent,name,true,i18n("Commit log"), + KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::Ok,true); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + + ptr = new Logmsg_impl(items,Dialog1Layout); + if (!rec) { + ptr->m_DepthSelector->hide(); + } + if (!keep_locks) { + ptr->m_keepLocksButton->hide(); + } + ptr->initHistory(); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),groupName)); + if (dlg.exec()!=QDialog::Accepted) { + _ok = false; + /* avoid compiler warnings */ + _rec = false; + _keep_locks=false; + } else { + _ok = true; + _depth = ptr->getDepth(); + msg=ptr->getMessage(); + _keep_locks = ptr->isKeeplocks(); + } + ptr->saveHistory(!_ok); + + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),groupName,false); + if (ok) *ok = _ok; + if (rec) *rec = _depth; + if (keep_locks) *keep_locks = _keep_locks; + return msg; +} + +QString Logmsg_impl::getLogmessage(const logActionEntries&_on, + const logActionEntries&_off, + QObject*callback, + logActionEntries&_result, + bool*ok,bool*keep_locks,QWidget*parent,const char*name) +{ + bool _ok,_keep_locks; + QString msg(""); + + Logmsg_impl*ptr=0; + KDialogBase dlg(parent,name,true,i18n("Commit log"), + KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::Ok,true); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + ptr = new Logmsg_impl(_on,_off,Dialog1Layout); + ptr->m_DepthSelector->hide(); + if (!keep_locks) { + ptr->m_keepLocksButton->hide(); + } + ptr->initHistory(); + if (callback) + { + connect(ptr,SIGNAL(makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + callback,SLOT(makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*))); + } + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),groupName)); + if (dlg.exec()!=QDialog::Accepted) { + _ok = false; + /* avoid compiler warnings */ + _keep_locks=false; + } else { + _ok = true; + msg=ptr->getMessage(); + _keep_locks = ptr->isKeeplocks(); + } + ptr->saveHistory(!_ok); + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),groupName,false); + if (ok) *ok = _ok; + _result = ptr->selectedEntries(); + if (keep_locks) *keep_locks = _keep_locks; + return msg; +} + +/*! + \fn Logmsg_impl::setRecCheckboxtext(const QString&what) + */ +void Logmsg_impl::addItemWidget(QWidget*aWidget) +{ + m_DepthSelector->addItemWidget(aWidget); +/* aWidget->reparent(this,geometry().topLeft()); + m_ItemsLayout->addWidget(aWidget); + kdDebug()<<"SizeHint: "<<aWidget->minimumSizeHint()<< endl; + aWidget->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + setMinimumHeight(minimumSizeHint().height());*/ +} + +Logmsg_impl::logActionEntries Logmsg_impl::selectedEntries() +{ + logActionEntries _result; + if (m_ReviewList) { + QListViewItemIterator it( m_ReviewList ); + while ( it.current() ) { + if (it.current()->rtti()==1000) { + SvnCheckListItem *item = static_cast<SvnCheckListItem*>(it.current()); + if (item->isOn()) { + _result.append(item->data()); + } + } + ++it; + } + } + return _result; +} + +Logmsg_impl::logActionEntry::logActionEntry(const QString&name,const QString&action,ACTION_TYPE kind) + : _name(name),_actionDesc(action),_kind(kind) +{ +} + +Logmsg_impl::logActionEntry::logActionEntry() + : _name(""),_actionDesc(""),_kind(COMMIT) +{ +} + +SvnCheckListItem::SvnCheckListItem(QListView*parent,const Logmsg_impl::logActionEntry&content) + :QCheckListItem(parent,content._name,QCheckListItem::CheckBox),m_Content(content) +{ + setTristate(FALSE); + setText(1,m_Content._actionDesc); + if (content._name.isEmpty()) { + setText(0,"..."); + } +} + +int SvnCheckListItem::compare( QListViewItem* item, int col, bool ascending ) const +{ + if (item->rtti()!=1000 || col>0) { + return QCheckListItem::compare(item,col,ascending); + } + SvnCheckListItem* k = static_cast<SvnCheckListItem*>( item ); + if (Kdesvnsettings::case_sensitive_sort()) { + if (Kdesvnsettings::locale_is_casesensitive()) { + return m_Content._name.lower().localeAwareCompare(k->m_Content._name.lower()); + } + return m_Content._name.compare(k->m_Content._name); + } else { + return m_Content._name.lower().localeAwareCompare(k->m_Content._name.lower()); + } +} + +void Logmsg_impl::slotUnmarkUnversioned() +{ + markUnversioned(false); +} + +void Logmsg_impl::slotMarkUnversioned() +{ + markUnversioned(true); +} + +void Logmsg_impl::slotDiffSelected() +{ + QListViewItem * it=0; + if (!m_ReviewList || !(it=m_ReviewList->selectedItem())) + { + return; + } + if (it->rtti()==1000) + { + SvnCheckListItem *item = static_cast<SvnCheckListItem*>(it); + QString what = item->data()._name; + emit makeDiff(what,svn::Revision::BASE,what,svn::Revision::WORKING,parentWidget()); + } +} + +void Logmsg_impl::hideButtons(bool how) +{ + if (!m_MarkUnversioned)return; + if (how) + { + m_MarkUnversioned->hide(); + m_UnmarkUnversioned->hide(); + m_DiffItem->hide(); + m_HideNewItems->hide(); + } + else + { + m_MarkUnversioned->show(); + m_UnmarkUnversioned->show(); + m_DiffItem->show(); + m_HideNewItems->show(); + } +} + +/*! + \fn Logmsg_impl::markUnversioned(bool mark) + */ +void Logmsg_impl::markUnversioned(bool mark) +{ + if (!m_ReviewList)return; + QListViewItemIterator it( m_ReviewList ); + while ( it.current() ) { + if (it.current()->rtti()==1000) { + SvnCheckListItem *item = static_cast<SvnCheckListItem*>(it.current()); + if (item->data()._kind==logActionEntry::ADD_COMMIT) { + item->setOn(mark); + } + } + ++it; + } +} + +void Logmsg_impl::hideNewItems(bool how) +{ + if (!m_ReviewList)return; + + if (how) { + QListViewItemIterator it( m_ReviewList ); + while ( it.current() ) { + if (it.current()->rtti()==1000) { + SvnCheckListItem *item = static_cast<SvnCheckListItem*>(it.current()); + if (item->data()._kind==logActionEntry::ADD_COMMIT) { + item->setOn(false); + m_Hidden.push_back(item); + } + } + ++it; + } + for (unsigned j=0;j<m_Hidden.size();++j) { + m_ReviewList->takeItem(m_Hidden[j]); + } + } else { + for (unsigned j=0;j<m_Hidden.size();++j) { + m_ReviewList->insertItem(m_Hidden[j]); + } + m_Hidden.clear(); + } +} + +/*! + \fn Logmsg_impl::hideDepth(bool hide) + */ +void Logmsg_impl::hideDepth(bool ahide) +{ + m_DepthSelector->hideDepth(ahide); +// if (hide) m_DepthSelector->hide(); +// else m_DepthSelector->show(); +} + +void Logmsg_impl::insertFile(const QString&fname) +{ + QFile ifs(fname); + if (ifs.open(IO_ReadOnly)) { + QTextStream ts(&ifs); + QString _content = ts.read(); + int para,index; + m_LogEdit->getCursorPosition(¶,&index); + m_LogEdit->insertAt(_content,para,index); + } +} + +void Logmsg_impl::insertFile() +{ + QString head = i18n("Select textfile for insert"); + KURLRequesterDlg dlg(QString::null,this,head); + dlg.setCaption(head); + KFile::Mode mode = static_cast<KFile::Mode>(KFile::File); + dlg.urlRequester()->setMode(mode); + dlg.urlRequester()->setCaption(head); + + if (dlg.exec()!=QDialog::Accepted) { + return; + } + KURL _url = dlg.selectedURL(); + if (_url.isEmpty() || !_url.isValid()) { + return; + } + if (_url.isLocalFile()) { + insertFile(_url.path()); + } else { + QString tmpFile; + if( KIO::NetAccess::download(_url, tmpFile, this) ) { + insertFile( tmpFile ); + KIO::NetAccess::removeTempFile( tmpFile ); + } else { + KMessageBox::error(this, KIO::NetAccess::lastErrorString() ); + } + } +} + +#include "logmsg_impl.moc" diff --git a/src/ksvnwidgets/logmsg_impl.h b/src/ksvnwidgets/logmsg_impl.h new file mode 100644 index 0000000..5d41ccf --- /dev/null +++ b/src/ksvnwidgets/logmsg_impl.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef LOGMSG_IMPL_H +#define LOGMSG_IMPL_H + +#include "src/ksvnwidgets/logmessage.h" +#include "src/svnqt/commititem.hpp" +#include <qvaluelist.h> +#include <qpair.h> + +class Logmsg_impl: public LogmessageData { +Q_OBJECT +public: + struct logActionEntry { + QString _name; + QString _actionDesc; + + enum ACTION_TYPE{ + COMMIT=0, + ADD_COMMIT=1, + DELETE=2, + MISSING_DELETE=3 + }; + ACTION_TYPE _kind; + logActionEntry(const QString&,const QString&,ACTION_TYPE kind = COMMIT); + logActionEntry(); + }; + + typedef QValueList<logActionEntry> logActionEntries; + + Logmsg_impl(QWidget *parent = 0, const char *name = 0); + Logmsg_impl(const svn::CommitItemList&_items,QWidget *parent=0, const char *name=0); + Logmsg_impl(const QMap<QString,QString>&_items,QWidget *parent=0, const char *name=0); + Logmsg_impl(const logActionEntries&, + const logActionEntries&, + QWidget *parent = 0, const char *name = 0); + virtual ~Logmsg_impl(); + + QString getMessage()const; + bool isKeeplocks()const; + void initHistory(); + void saveHistory(bool canceld); + + static QString getLogmessage(bool*ok,svn::Depth*rec,bool*keeps_locks,QWidget*parent=0,const char*name=0); + static QString getLogmessage(const svn::CommitItemList&,bool*ok,svn::Depth*rec,bool*keep_locks,QWidget*parent=0,const char*name=0); + static QString getLogmessage(const QMap<QString,QString>&,bool*ok,svn::Depth*rec,bool*keep_locks,QWidget*parent=0,const char*name=0); + + static QString getLogmessage(const logActionEntries&, + const logActionEntries&, + QObject*callback, + logActionEntries&, + bool*ok,bool*keep_locks,QWidget*parent=0,const char*name=0); + + void addItemWidget(QWidget*); + + svn::Depth getDepth()const; + + logActionEntries selectedEntries(); + void hideDepth(bool ahide); + +protected slots: + virtual void slotHistoryActivated(int); + virtual void slotUnmarkUnversioned(); + virtual void slotDiffSelected(); + virtual void slotMarkUnversioned(); + virtual void hideNewItems(bool); + virtual void insertFile(); + +protected: + static QValueList<QString> sLogHistory; + QValueList<QListViewItem*> m_Hidden; + static const QString groupName; + static QString sLastMessage; + static unsigned int smax_message_history; + bool m_hidden; + + void hideButtons(bool); + void markUnversioned(bool mark); + void checkSplitterSize(); + virtual void insertFile(const QString&); +signals: + void makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); +}; + +#endif diff --git a/src/ksvnwidgets/pwstorage.cpp b/src/ksvnwidgets/pwstorage.cpp new file mode 100644 index 0000000..c239b5a --- /dev/null +++ b/src/ksvnwidgets/pwstorage.cpp @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "pwstorage.h" +#include "kdesvn-config.h" +#include "src/settings/kdesvnsettings.h" + +#include <kwallet.h> +#include <kwin.h> +#include <kapp.h> + +#include <qthread.h> +#include <qmap.h> +#include <qpair.h> + +class PwStorageData +{ +public: + + PwStorageData(){ + m_Wallet=0; + } + + ~PwStorageData() + { + delete m_Wallet; + m_Wallet=0; + } + + KWallet::Wallet*getWallet(); + + typedef QPair<QString,QString> userpw_type; + typedef QMap<QString, userpw_type> cache_type; + + cache_type*getLoginCache(); + + QMutex*getCacheMutex(); + +protected: + KWallet::Wallet* m_Wallet; + +}; + +QMutex*PwStorageData::getCacheMutex() +{ + static QMutex _mutex; + return &_mutex; +} + +PwStorageData::cache_type*PwStorageData::getLoginCache() +{ + static PwStorageData::cache_type _LoginCache; + return &_LoginCache; +} + +KWallet::Wallet*PwStorageData::getWallet() +{ + static bool walletOpenFailed = false; + if (m_Wallet && m_Wallet->isOpen()) { + return m_Wallet; + } + + if (KWallet::Wallet::isEnabled()) { + WId window = 0; + if ( qApp->activeWindow() ) { + window = qApp->activeWindow()->winId(); + } + delete m_Wallet; + m_Wallet = KWallet::Wallet::openWallet( KWallet::Wallet::NetworkWallet(),window); + } + if (!m_Wallet) { + walletOpenFailed = true; + } else { + if (!m_Wallet->hasFolder(WALLETNAME)) { + m_Wallet->createFolder(WALLETNAME); + } + m_Wallet->setFolder(WALLETNAME); + } + return m_Wallet; +} + +PwStorage*PwStorage::self() +{ + static PwStorage*_me = 0; + if (!_me) { + _me = new PwStorage(); + } + return _me; +} + +/*! + \fn PwStorage::PwStorageData() + */ +PwStorage::PwStorage() + :QObject() +{ + mData = new PwStorageData; +} + +/*! + \fn PwStorage::~PwStorageData() + */ +PwStorage::~PwStorage() +{ + delete mData; +} + + +/*! + \fn PwStorage::connectWallet() + */ +bool PwStorage::connectWallet() +{ + return mData->getWallet()!=0L; +} + +/*! + \fn PwStorage::getCertPw(const QString&realm,QString&pw) + */ +bool PwStorage::getCertPw(const QString&realm,QString&pw) +{ + if (!mData->getWallet()) { + return false; + } + return (mData->getWallet()->readPassword(realm,pw)==0); +} + + +/*! + \fn PwStorage::getLogin(const QString&realm,QString&user,QString&pw) + */ +bool PwStorage::getLogin(const QString&realm,QString&user,QString&pw) +{ + if (!mData->getWallet()) { + return false; + } + QMap<QString,QString> content; + int j = mData->getWallet()->readMap(realm,content); + if (j!=0||content.find("user")==content.end()) { + return true; + } + user = content["user"]; + pw = content["password"]; + return true; +} + +bool PwStorage::getCachedLogin(const QString&realm,QString&user,QString&pw) +{ + QMutexLocker lc(mData->getCacheMutex()); + PwStorageData::cache_type::ConstIterator it = mData->getLoginCache()->find(realm); + if (it!=mData->getLoginCache()->end()) { + user=(*it).first; + pw = (*it).second; + } + return true; +} + +/*! + \fn PwStorage::setCertPw(const QString&realm, const QString&pw) + */ +bool PwStorage::setCertPw(const QString&realm, const QString&pw) +{ + if (!mData->getWallet()) { + return false; + } + return (mData->getWallet()->writePassword(realm,pw)==0); +} + + +/*! + \fn PwStorage::setLogin(const QString&realm,const QString&user,const QString&pw) + */ +bool PwStorage::setLogin(const QString&realm,const QString&user,const QString&pw) +{ + if (!mData->getWallet()) { + return false; + } + QMap<QString,QString> content; + content["user"]=user; + content["password"]=pw; + return (mData->getWallet()->writeMap(realm,content)==0); +} + +bool PwStorage::setCachedLogin(const QString&realm,const QString&user,const QString&pw) +{ + QMutexLocker lc(mData->getCacheMutex()); + PwStorageData::cache_type*_Cache = mData->getLoginCache(); + (*_Cache)[realm]=PwStorageData::userpw_type(user,pw); + return true; +} + +#include "pwstorage.moc" diff --git a/src/ksvnwidgets/pwstorage.h b/src/ksvnwidgets/pwstorage.h new file mode 100644 index 0000000..93e9680 --- /dev/null +++ b/src/ksvnwidgets/pwstorage.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _PWSTORAGE_H +#define _PWSTORAGE_H + +#include <qstring.h> +#include <qobject.h> + +class PwStorageData; + +/** + Access to wallet isn't threadsafe 'cause wallet has not to be called from within threads! + */ +class PwStorage:public QObject +{ + Q_OBJECT +protected: + PwStorageData* mData; +public: + bool getCertPw(const QString&realm,QString&pw); + bool getLogin(const QString&realm,QString&user,QString&pw); + bool getCachedLogin(const QString&realm,QString&user,QString&pw); + bool setCertPw(const QString&realm, const QString&pw); + bool setLogin(const QString&realm,const QString&user,const QString&pw); + bool setCachedLogin(const QString&realm,const QString&user,const QString&pw); + bool connectWallet(); + + static PwStorage*self(); + +protected: + PwStorage(); + virtual ~PwStorage(); +}; + +#endif + diff --git a/src/ksvnwidgets/revertform.ui b/src/ksvnwidgets/revertform.ui new file mode 100644 index 0000000..37ee867 --- /dev/null +++ b/src/ksvnwidgets/revertform.ui @@ -0,0 +1,89 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>RevertForm</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RevertForm</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>276</width> + <height>162</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + <property name="caption"> + <string>Revert</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_headLine</cstring> + </property> + <property name="text"> + <string>Really revert these entries to pristine state?</string> + </property> + </widget> + <widget class="QListBox"> + <property name="name"> + <cstring>m_ItemsList</cstring> + </property> + </widget> + <widget class="DepthSelector"> + <property name="name"> + <cstring>m_DepthSelect</cstring> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>DepthSelector</class> + <header location="local">src/ksvnwidgets/depthselector.h</header> + <sizehint> + <width>-1</width> + <height>30</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>src/ksvnwidgets/depthselector.h</includehint> +</includehints> +</UI> diff --git a/src/ksvnwidgets/revertform_impl.cpp b/src/ksvnwidgets/revertform_impl.cpp new file mode 100644 index 0000000..8dada74 --- /dev/null +++ b/src/ksvnwidgets/revertform_impl.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "revertform_impl.h" +#include "depthselector.h" + +#include <qstringlist.h> +#include <qlistbox.h> + +/*! + \fn RevertFormImpl::RevertFormImpl(QWidget*parent,const char*name) + */ + RevertFormImpl::RevertFormImpl(QWidget*parent,const char*name) + :RevertForm(parent,name) +{ + setMinimumSize(minimumSizeHint()); +} + +/*! + \fn RevertFormImpl::~RevertFormImpl() + */ +RevertFormImpl::~RevertFormImpl() +{ + /// @todo implement me +} + +svn::Depth RevertFormImpl::getDepth()const +{ + return m_DepthSelect->getDepth(); +} + + +/*! + \fn RevertFormImpl::setDispList(const QStringList&_list) + */ +void RevertFormImpl::setDispList(const QStringList&_list) +{ + m_ItemsList->insertStringList(_list); +} + +#include "revertform_impl.moc" diff --git a/src/ksvnwidgets/revertform_impl.h b/src/ksvnwidgets/revertform_impl.h new file mode 100644 index 0000000..1cf7cd6 --- /dev/null +++ b/src/ksvnwidgets/revertform_impl.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _REVERT_FORM_IMPL_H +#define _REVERT_FORM_IMPL_H + +#include "src/ksvnwidgets/revertform.h" +#include "src/svnqt/svnqttypes.hpp" + +class QStringList; + +class RevertFormImpl:public RevertForm +{ + Q_OBJECT +public: + RevertFormImpl(QWidget*parent=0,const char*name=0); + virtual ~RevertFormImpl(); + svn::Depth getDepth()const; + void setDispList(const QStringList&_list); +}; + +#endif diff --git a/src/ksvnwidgets/ssltrustprompt.ui b/src/ksvnwidgets/ssltrustprompt.ui new file mode 100644 index 0000000..2cfb488 --- /dev/null +++ b/src/ksvnwidgets/ssltrustprompt.ui @@ -0,0 +1,40 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>SslTrustPrompt</class> +<widget class="QWidget"> + <property name="name"> + <cstring>SslTrustPrompt</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>303</width> + <height>185</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_MainLabel</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KTextBrowser"> + <property name="name"> + <cstring>m_ContentText</cstring> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>ktextbrowser.h</includehint> +</includehints> +</UI> diff --git a/src/ksvnwidgets/ssltrustprompt_impl.cpp b/src/ksvnwidgets/ssltrustprompt_impl.cpp new file mode 100644 index 0000000..795fe66 --- /dev/null +++ b/src/ksvnwidgets/ssltrustprompt_impl.cpp @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "ssltrustprompt_impl.h" +#include "src/settings/kdesvnsettings.h" + +#include <klocale.h> +#include <qlabel.h> +#include <qtable.h> +#include <qvbox.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kapp.h> +#include <kconfigbase.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <ktextbrowser.h> + +SslTrustPrompt_impl::SslTrustPrompt_impl(const QString&host,QWidget *parent, const char *name) + :SslTrustPrompt(parent, name) +{ + m_MainLabel->setText("<p align=\"center\"><b>"+ + i18n("Error validating server certificate for '%1'").arg(host)+ + QString("</b></p>")); +} + + +/*! + \fn SslTrustPrompt_impl::sslTrust(const QString&host,const QString&fingerprint,const QString&validFrom,const QString&validUntil,const QString&issuerName,const QString&realm,bool*ok,bool*saveit) + */ +bool SslTrustPrompt_impl::sslTrust(const QString&host,const QString&fingerprint,const QString&validFrom,const QString&validUntil,const QString&issuerName,const QString&realm,const QStringList&reasons,bool*ok,bool*saveit) +{ + SslTrustPrompt_impl*ptr=0; + KDialogBase dlg(i18n("Trust ssl certificate")); + dlg.setButtonText(KDialogBase::Yes,i18n("Accept permanently")); + dlg.setButtonText(KDialogBase::No,i18n("Accept temporarily")); + dlg.setButtonCancel(KGuiItem(i18n("Reject"))); + + static QString rb = "<tr><td>"; + static QString rs = "</td><td>"; + static QString re = "</td></tr>"; + QString text = "<html><body>"; + if (reasons.count()>0) { + text+="<p align=\"center\">"; + text+="<h2>"+i18n("Failure reasons")+"</h2><hline>"; + for (unsigned int i = 0; i < reasons.count();++i) { + text+=reasons[i]+"<br><hline>"; + } + text+="</p>"; + } + + text+="<p align=\"center\"><table>"; + text+=rb+i18n("Realm")+rs+realm+re; + text+=rb+i18n("Host")+rs+host+re; + text+=rb+i18n("Valid from")+rs+validFrom+re; + text+=rb+i18n("Valid until")+rs+validUntil+re; + text+=rb+i18n("Issuer name")+rs+issuerName+re; + text+=rb+i18n("Fingerprint")+rs+fingerprint+re; + text+="</table></p></body></html>"; + + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),"trustssldlg")); + ptr = new SslTrustPrompt_impl(host,Dialog1Layout); + ptr->m_ContentText->setText(text); + int i = dlg.exec(); + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"trustssldlg",false); + *saveit = false; + *ok = true; + if (i == KDialogBase::Yes) { + *saveit = true; + } else if (i==KDialogBase::Cancel) { + *ok = false; + } + return *ok; +} +#include "ssltrustprompt_impl.moc" diff --git a/src/ksvnwidgets/ssltrustprompt_impl.h b/src/ksvnwidgets/ssltrustprompt_impl.h new file mode 100644 index 0000000..5ea5cd3 --- /dev/null +++ b/src/ksvnwidgets/ssltrustprompt_impl.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SSLTRUSTPROMPT_IMPL_H +#define SSLTRUSTPROMPT_IMPL_H + +#include "src/ksvnwidgets/ssltrustprompt.h" + +class SslTrustPrompt_impl: public SslTrustPrompt { +Q_OBJECT +public: + SslTrustPrompt_impl(const QString&,QWidget *parent = 0, const char *name = 0); + static bool sslTrust(const QString&host,const QString&fingerprint,const QString&validFrom,const QString&validUntil,const QString&issuerName,const QString&realm,const QStringList&reasons,bool*ok,bool*saveit); +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..cee2ef2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "kdesvn.h" +#include "commandline.h" +#include "kdesvn-config.h" +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <kdebug.h> + +static const char description[] = + I18N_NOOP("A Subversion Client for KDE (standalone application)"); + +static const char version[] = VERSION; + +static KCmdLineOptions options[] = +{ + { "r startrev[:endrev]",I18N_NOOP("Execute single subversion command on specific revision(-range)"),0}, + {"R",I18N_NOOP("Ask for revision when executing single command"),0}, + {"f",I18N_NOOP("Force operation"),0}, + {"o <file>",I18N_NOOP("Save output of subversion command (eg \"cat\") into file <file>"),0}, + {"l <number>",I18N_NOOP("Limit log output to <number>"),0}, + { "+exec <command>",I18N_NOOP("Execute subversion command (\"exec help\" for more information)"),0}, + { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + KAboutData about("kdesvn", I18N_NOOP("kdesvn"), version, description, + KAboutData::License_GPL, "(C) 2005-2007 Rajko Albrecht",0, + 0, "ral@alwins-world.de"); + about.addAuthor( "Rajko Albrecht", 0, "ral@alwins-world.de" ); + about.setHomepage("http://kdesvn.alwins-world.de/"); + about.setBugAddress("kdesvn-bugs@alwins-world.de"); + + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + + + KApplication app; + + // see if we are starting with session management + if (app.isRestored()) + { + RESTORE(kdesvn); + } + else + { + // no session.. just start up normally + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if (args->count() == 0) + { + kdesvn *widget = new kdesvn; + widget->show(); + widget->checkReload(); + } + else + { + if (QString(args->arg(0))==QString("exec")) { + kdDebug()<<"Execute a command" << endl; + CommandLine cl(args); + return cl.exec(); + } else { + int i = 0; + for (; i < args->count(); i++) + { + kdesvn *widget = new kdesvn; + widget->show(); + widget->load(args->url(i),true); + } + } + } + args->clear(); + } + return app.exec(); +} diff --git a/src/pics/CMakeLists.txt b/src/pics/CMakeLists.txt new file mode 100644 index 0000000..e70476e --- /dev/null +++ b/src/pics/CMakeLists.txt @@ -0,0 +1,2 @@ +KDESVN_INSTALL_ICONS(hicolor) + diff --git a/src/pics/hi128-action-kdesvnadd.png b/src/pics/hi128-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..ec85bf3 --- /dev/null +++ b/src/pics/hi128-action-kdesvnadd.png diff --git a/src/pics/hi128-action-kdesvnaddrecursive.png b/src/pics/hi128-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..652a120 --- /dev/null +++ b/src/pics/hi128-action-kdesvnaddrecursive.png diff --git a/src/pics/hi128-action-kdesvnblame.png b/src/pics/hi128-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..b4be8ad --- /dev/null +++ b/src/pics/hi128-action-kdesvnblame.png diff --git a/src/pics/hi128-action-kdesvncat.png b/src/pics/hi128-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..1dcfadc --- /dev/null +++ b/src/pics/hi128-action-kdesvncat.png diff --git a/src/pics/hi128-action-kdesvncheckout.png b/src/pics/hi128-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..afe780b --- /dev/null +++ b/src/pics/hi128-action-kdesvncheckout.png diff --git a/src/pics/hi128-action-kdesvncheckupdates.png b/src/pics/hi128-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..de70df0 --- /dev/null +++ b/src/pics/hi128-action-kdesvncheckupdates.png diff --git a/src/pics/hi128-action-kdesvncleanup.png b/src/pics/hi128-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..33278d9 --- /dev/null +++ b/src/pics/hi128-action-kdesvncleanup.png diff --git a/src/pics/hi128-action-kdesvncommit.png b/src/pics/hi128-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..d4e5bf8 --- /dev/null +++ b/src/pics/hi128-action-kdesvncommit.png diff --git a/src/pics/hi128-action-kdesvncopy.png b/src/pics/hi128-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..2e64462 --- /dev/null +++ b/src/pics/hi128-action-kdesvncopy.png diff --git a/src/pics/hi128-action-kdesvndelete.png b/src/pics/hi128-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..a5349b1 --- /dev/null +++ b/src/pics/hi128-action-kdesvndelete.png diff --git a/src/pics/hi128-action-kdesvndiff.png b/src/pics/hi128-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..23327ec --- /dev/null +++ b/src/pics/hi128-action-kdesvndiff.png diff --git a/src/pics/hi128-action-kdesvnexport.png b/src/pics/hi128-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..8172bf3 --- /dev/null +++ b/src/pics/hi128-action-kdesvnexport.png diff --git a/src/pics/hi128-action-kdesvninfo.png b/src/pics/hi128-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..f217632 --- /dev/null +++ b/src/pics/hi128-action-kdesvninfo.png diff --git a/src/pics/hi128-action-kdesvnlock.png b/src/pics/hi128-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..2344c58 --- /dev/null +++ b/src/pics/hi128-action-kdesvnlock.png diff --git a/src/pics/hi128-action-kdesvnlog.png b/src/pics/hi128-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..1e06b9c --- /dev/null +++ b/src/pics/hi128-action-kdesvnlog.png diff --git a/src/pics/hi128-action-kdesvnmerge.png b/src/pics/hi128-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..73a80a9 --- /dev/null +++ b/src/pics/hi128-action-kdesvnmerge.png diff --git a/src/pics/hi128-action-kdesvnrelocate.png b/src/pics/hi128-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..aedbf77 --- /dev/null +++ b/src/pics/hi128-action-kdesvnrelocate.png diff --git a/src/pics/hi128-action-kdesvnswitch.png b/src/pics/hi128-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..347c432 --- /dev/null +++ b/src/pics/hi128-action-kdesvnswitch.png diff --git a/src/pics/hi128-action-kdesvnunlock.png b/src/pics/hi128-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..ba0aeca --- /dev/null +++ b/src/pics/hi128-action-kdesvnunlock.png diff --git a/src/pics/hi128-action-kdesvnupdate.png b/src/pics/hi128-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..40e5dc1 --- /dev/null +++ b/src/pics/hi128-action-kdesvnupdate.png diff --git a/src/pics/hi128-filesys-kdesvnadded.png b/src/pics/hi128-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..e01579d --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnadded.png diff --git a/src/pics/hi128-filesys-kdesvnconflicted.png b/src/pics/hi128-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..61f9db7 --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnconflicted.png diff --git a/src/pics/hi128-filesys-kdesvndeleted.png b/src/pics/hi128-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..ca3b090 --- /dev/null +++ b/src/pics/hi128-filesys-kdesvndeleted.png diff --git a/src/pics/hi128-filesys-kdesvnlocked.png b/src/pics/hi128-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..ee0bc7c --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnlocked.png diff --git a/src/pics/hi128-filesys-kdesvnmodified.png b/src/pics/hi128-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..3042eb4 --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnmodified.png diff --git a/src/pics/hi128-filesys-kdesvnneedlock.png b/src/pics/hi128-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..d057ea2 --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnneedlock.png diff --git a/src/pics/hi128-filesys-kdesvnupdates.png b/src/pics/hi128-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..3902655 --- /dev/null +++ b/src/pics/hi128-filesys-kdesvnupdates.png diff --git a/src/pics/hi16-action-kdesvnadd.png b/src/pics/hi16-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..35345dc --- /dev/null +++ b/src/pics/hi16-action-kdesvnadd.png diff --git a/src/pics/hi16-action-kdesvnaddrecursive.png b/src/pics/hi16-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..fa7fa5b --- /dev/null +++ b/src/pics/hi16-action-kdesvnaddrecursive.png diff --git a/src/pics/hi16-action-kdesvnblame.png b/src/pics/hi16-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..916a8b6 --- /dev/null +++ b/src/pics/hi16-action-kdesvnblame.png diff --git a/src/pics/hi16-action-kdesvncat.png b/src/pics/hi16-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..dda0d75 --- /dev/null +++ b/src/pics/hi16-action-kdesvncat.png diff --git a/src/pics/hi16-action-kdesvncheckout.png b/src/pics/hi16-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..15181f7 --- /dev/null +++ b/src/pics/hi16-action-kdesvncheckout.png diff --git a/src/pics/hi16-action-kdesvncheckupdates.png b/src/pics/hi16-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..fe02543 --- /dev/null +++ b/src/pics/hi16-action-kdesvncheckupdates.png diff --git a/src/pics/hi16-action-kdesvncleanup.png b/src/pics/hi16-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..71068aa --- /dev/null +++ b/src/pics/hi16-action-kdesvncleanup.png diff --git a/src/pics/hi16-action-kdesvncommit.png b/src/pics/hi16-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..d6d0897 --- /dev/null +++ b/src/pics/hi16-action-kdesvncommit.png diff --git a/src/pics/hi16-action-kdesvncopy.png b/src/pics/hi16-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..d8e09ae --- /dev/null +++ b/src/pics/hi16-action-kdesvncopy.png diff --git a/src/pics/hi16-action-kdesvndelete.png b/src/pics/hi16-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..305d575 --- /dev/null +++ b/src/pics/hi16-action-kdesvndelete.png diff --git a/src/pics/hi16-action-kdesvndiff.png b/src/pics/hi16-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..c1ba50e --- /dev/null +++ b/src/pics/hi16-action-kdesvndiff.png diff --git a/src/pics/hi16-action-kdesvnexport.png b/src/pics/hi16-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..1c7e61e --- /dev/null +++ b/src/pics/hi16-action-kdesvnexport.png diff --git a/src/pics/hi16-action-kdesvninfo.png b/src/pics/hi16-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..c9a28e8 --- /dev/null +++ b/src/pics/hi16-action-kdesvninfo.png diff --git a/src/pics/hi16-action-kdesvnlock.png b/src/pics/hi16-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..2761f9c --- /dev/null +++ b/src/pics/hi16-action-kdesvnlock.png diff --git a/src/pics/hi16-action-kdesvnlog.png b/src/pics/hi16-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..eda6262 --- /dev/null +++ b/src/pics/hi16-action-kdesvnlog.png diff --git a/src/pics/hi16-action-kdesvnmerge.png b/src/pics/hi16-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..b9a20c2 --- /dev/null +++ b/src/pics/hi16-action-kdesvnmerge.png diff --git a/src/pics/hi16-action-kdesvnrelocate.png b/src/pics/hi16-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..1f1d713 --- /dev/null +++ b/src/pics/hi16-action-kdesvnrelocate.png diff --git a/src/pics/hi16-action-kdesvnswitch.png b/src/pics/hi16-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..ad3aa63 --- /dev/null +++ b/src/pics/hi16-action-kdesvnswitch.png diff --git a/src/pics/hi16-action-kdesvnunlock.png b/src/pics/hi16-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..e7ea487 --- /dev/null +++ b/src/pics/hi16-action-kdesvnunlock.png diff --git a/src/pics/hi16-action-kdesvnupdate.png b/src/pics/hi16-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..831e438 --- /dev/null +++ b/src/pics/hi16-action-kdesvnupdate.png diff --git a/src/pics/hi16-filesys-kdesvnadded.png b/src/pics/hi16-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..64da421 --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnadded.png diff --git a/src/pics/hi16-filesys-kdesvnconflicted.png b/src/pics/hi16-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..9f22f74 --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnconflicted.png diff --git a/src/pics/hi16-filesys-kdesvndeleted.png b/src/pics/hi16-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..873dab5 --- /dev/null +++ b/src/pics/hi16-filesys-kdesvndeleted.png diff --git a/src/pics/hi16-filesys-kdesvnlocked.png b/src/pics/hi16-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..e6c49e2 --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnlocked.png diff --git a/src/pics/hi16-filesys-kdesvnmodified.png b/src/pics/hi16-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..845a3dd --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnmodified.png diff --git a/src/pics/hi16-filesys-kdesvnneedlock.png b/src/pics/hi16-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..5f75f1c --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnneedlock.png diff --git a/src/pics/hi16-filesys-kdesvnupdates.png b/src/pics/hi16-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..7a26323 --- /dev/null +++ b/src/pics/hi16-filesys-kdesvnupdates.png diff --git a/src/pics/hi22-action-kdesvnadd.png b/src/pics/hi22-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..b6ca728 --- /dev/null +++ b/src/pics/hi22-action-kdesvnadd.png diff --git a/src/pics/hi22-action-kdesvnaddrecursive.png b/src/pics/hi22-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..2e895d1 --- /dev/null +++ b/src/pics/hi22-action-kdesvnaddrecursive.png diff --git a/src/pics/hi22-action-kdesvnblame.png b/src/pics/hi22-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..68fc873 --- /dev/null +++ b/src/pics/hi22-action-kdesvnblame.png diff --git a/src/pics/hi22-action-kdesvncat.png b/src/pics/hi22-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..7d0cf00 --- /dev/null +++ b/src/pics/hi22-action-kdesvncat.png diff --git a/src/pics/hi22-action-kdesvncheckout.png b/src/pics/hi22-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..c503f86 --- /dev/null +++ b/src/pics/hi22-action-kdesvncheckout.png diff --git a/src/pics/hi22-action-kdesvncheckupdates.png b/src/pics/hi22-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..d7ab034 --- /dev/null +++ b/src/pics/hi22-action-kdesvncheckupdates.png diff --git a/src/pics/hi22-action-kdesvncleanup.png b/src/pics/hi22-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..dc16ece --- /dev/null +++ b/src/pics/hi22-action-kdesvncleanup.png diff --git a/src/pics/hi22-action-kdesvncommit.png b/src/pics/hi22-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..5a9e115 --- /dev/null +++ b/src/pics/hi22-action-kdesvncommit.png diff --git a/src/pics/hi22-action-kdesvncopy.png b/src/pics/hi22-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..6e58402 --- /dev/null +++ b/src/pics/hi22-action-kdesvncopy.png diff --git a/src/pics/hi22-action-kdesvndelete.png b/src/pics/hi22-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..6ad3d90 --- /dev/null +++ b/src/pics/hi22-action-kdesvndelete.png diff --git a/src/pics/hi22-action-kdesvndiff.png b/src/pics/hi22-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..c0352d7 --- /dev/null +++ b/src/pics/hi22-action-kdesvndiff.png diff --git a/src/pics/hi22-action-kdesvnexport.png b/src/pics/hi22-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..8bdfef2 --- /dev/null +++ b/src/pics/hi22-action-kdesvnexport.png diff --git a/src/pics/hi22-action-kdesvninfo.png b/src/pics/hi22-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..6431103 --- /dev/null +++ b/src/pics/hi22-action-kdesvninfo.png diff --git a/src/pics/hi22-action-kdesvnlock.png b/src/pics/hi22-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..ed54f69 --- /dev/null +++ b/src/pics/hi22-action-kdesvnlock.png diff --git a/src/pics/hi22-action-kdesvnlog.png b/src/pics/hi22-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..c611ee8 --- /dev/null +++ b/src/pics/hi22-action-kdesvnlog.png diff --git a/src/pics/hi22-action-kdesvnmerge.png b/src/pics/hi22-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..667cd0b --- /dev/null +++ b/src/pics/hi22-action-kdesvnmerge.png diff --git a/src/pics/hi22-action-kdesvnrelocate.png b/src/pics/hi22-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..13338b7 --- /dev/null +++ b/src/pics/hi22-action-kdesvnrelocate.png diff --git a/src/pics/hi22-action-kdesvnswitch.png b/src/pics/hi22-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..cd4af40 --- /dev/null +++ b/src/pics/hi22-action-kdesvnswitch.png diff --git a/src/pics/hi22-action-kdesvnunlock.png b/src/pics/hi22-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..5fd89a2 --- /dev/null +++ b/src/pics/hi22-action-kdesvnunlock.png diff --git a/src/pics/hi22-action-kdesvnupdate.png b/src/pics/hi22-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..6e4ade0 --- /dev/null +++ b/src/pics/hi22-action-kdesvnupdate.png diff --git a/src/pics/hi22-filesys-kdesvnadded.png b/src/pics/hi22-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..67a1c6b --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnadded.png diff --git a/src/pics/hi22-filesys-kdesvnconflicted.png b/src/pics/hi22-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..a56af88 --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnconflicted.png diff --git a/src/pics/hi22-filesys-kdesvndeleted.png b/src/pics/hi22-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..25f833a --- /dev/null +++ b/src/pics/hi22-filesys-kdesvndeleted.png diff --git a/src/pics/hi22-filesys-kdesvnlocked.png b/src/pics/hi22-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..0976210 --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnlocked.png diff --git a/src/pics/hi22-filesys-kdesvnmodified.png b/src/pics/hi22-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..ecd0a3c --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnmodified.png diff --git a/src/pics/hi22-filesys-kdesvnneedlock.png b/src/pics/hi22-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..df069aa --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnneedlock.png diff --git a/src/pics/hi22-filesys-kdesvnupdates.png b/src/pics/hi22-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..8c25bb1 --- /dev/null +++ b/src/pics/hi22-filesys-kdesvnupdates.png diff --git a/src/pics/hi32-action-kdesvnadd.png b/src/pics/hi32-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..08ef8c3 --- /dev/null +++ b/src/pics/hi32-action-kdesvnadd.png diff --git a/src/pics/hi32-action-kdesvnaddrecursive.png b/src/pics/hi32-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..ecd1585 --- /dev/null +++ b/src/pics/hi32-action-kdesvnaddrecursive.png diff --git a/src/pics/hi32-action-kdesvnblame.png b/src/pics/hi32-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..250e546 --- /dev/null +++ b/src/pics/hi32-action-kdesvnblame.png diff --git a/src/pics/hi32-action-kdesvncat.png b/src/pics/hi32-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..c0a09b2 --- /dev/null +++ b/src/pics/hi32-action-kdesvncat.png diff --git a/src/pics/hi32-action-kdesvncheckout.png b/src/pics/hi32-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..c632310 --- /dev/null +++ b/src/pics/hi32-action-kdesvncheckout.png diff --git a/src/pics/hi32-action-kdesvncheckupdates.png b/src/pics/hi32-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..bda22e7 --- /dev/null +++ b/src/pics/hi32-action-kdesvncheckupdates.png diff --git a/src/pics/hi32-action-kdesvncleanup.png b/src/pics/hi32-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..de37cb4 --- /dev/null +++ b/src/pics/hi32-action-kdesvncleanup.png diff --git a/src/pics/hi32-action-kdesvncommit.png b/src/pics/hi32-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..8767be3 --- /dev/null +++ b/src/pics/hi32-action-kdesvncommit.png diff --git a/src/pics/hi32-action-kdesvncopy.png b/src/pics/hi32-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..ae8050c --- /dev/null +++ b/src/pics/hi32-action-kdesvncopy.png diff --git a/src/pics/hi32-action-kdesvndelete.png b/src/pics/hi32-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..d37b48f --- /dev/null +++ b/src/pics/hi32-action-kdesvndelete.png diff --git a/src/pics/hi32-action-kdesvndiff.png b/src/pics/hi32-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..7e47c3e --- /dev/null +++ b/src/pics/hi32-action-kdesvndiff.png diff --git a/src/pics/hi32-action-kdesvnexport.png b/src/pics/hi32-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..cbd7db1 --- /dev/null +++ b/src/pics/hi32-action-kdesvnexport.png diff --git a/src/pics/hi32-action-kdesvninfo.png b/src/pics/hi32-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..1bec01b --- /dev/null +++ b/src/pics/hi32-action-kdesvninfo.png diff --git a/src/pics/hi32-action-kdesvnlock.png b/src/pics/hi32-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..0172993 --- /dev/null +++ b/src/pics/hi32-action-kdesvnlock.png diff --git a/src/pics/hi32-action-kdesvnlog.png b/src/pics/hi32-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..7601723 --- /dev/null +++ b/src/pics/hi32-action-kdesvnlog.png diff --git a/src/pics/hi32-action-kdesvnmerge.png b/src/pics/hi32-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..26e070a --- /dev/null +++ b/src/pics/hi32-action-kdesvnmerge.png diff --git a/src/pics/hi32-action-kdesvnrelocate.png b/src/pics/hi32-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..3e9b844 --- /dev/null +++ b/src/pics/hi32-action-kdesvnrelocate.png diff --git a/src/pics/hi32-action-kdesvnswitch.png b/src/pics/hi32-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..8ae8661 --- /dev/null +++ b/src/pics/hi32-action-kdesvnswitch.png diff --git a/src/pics/hi32-action-kdesvnunlock.png b/src/pics/hi32-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..a3a93a0 --- /dev/null +++ b/src/pics/hi32-action-kdesvnunlock.png diff --git a/src/pics/hi32-action-kdesvnupdate.png b/src/pics/hi32-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..a47e051 --- /dev/null +++ b/src/pics/hi32-action-kdesvnupdate.png diff --git a/src/pics/hi32-filesys-kdesvnadded.png b/src/pics/hi32-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..d4fce75 --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnadded.png diff --git a/src/pics/hi32-filesys-kdesvnconflicted.png b/src/pics/hi32-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..ae4e1dd --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnconflicted.png diff --git a/src/pics/hi32-filesys-kdesvndeleted.png b/src/pics/hi32-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..50df8d5 --- /dev/null +++ b/src/pics/hi32-filesys-kdesvndeleted.png diff --git a/src/pics/hi32-filesys-kdesvnlocked.png b/src/pics/hi32-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..f060a5b --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnlocked.png diff --git a/src/pics/hi32-filesys-kdesvnmodified.png b/src/pics/hi32-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..768be1b --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnmodified.png diff --git a/src/pics/hi32-filesys-kdesvnneedlock.png b/src/pics/hi32-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..62c9999 --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnneedlock.png diff --git a/src/pics/hi32-filesys-kdesvnupdates.png b/src/pics/hi32-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..5b5dc8b --- /dev/null +++ b/src/pics/hi32-filesys-kdesvnupdates.png diff --git a/src/pics/hi48-action-kdesvnadd.png b/src/pics/hi48-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..11486e0 --- /dev/null +++ b/src/pics/hi48-action-kdesvnadd.png diff --git a/src/pics/hi48-action-kdesvnaddrecursive.png b/src/pics/hi48-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..4488ffe --- /dev/null +++ b/src/pics/hi48-action-kdesvnaddrecursive.png diff --git a/src/pics/hi48-action-kdesvnblame.png b/src/pics/hi48-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..60f57e2 --- /dev/null +++ b/src/pics/hi48-action-kdesvnblame.png diff --git a/src/pics/hi48-action-kdesvncat.png b/src/pics/hi48-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..ba24992 --- /dev/null +++ b/src/pics/hi48-action-kdesvncat.png diff --git a/src/pics/hi48-action-kdesvncheckout.png b/src/pics/hi48-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..4d8558a --- /dev/null +++ b/src/pics/hi48-action-kdesvncheckout.png diff --git a/src/pics/hi48-action-kdesvncheckupdates.png b/src/pics/hi48-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..81a9be7 --- /dev/null +++ b/src/pics/hi48-action-kdesvncheckupdates.png diff --git a/src/pics/hi48-action-kdesvncleanup.png b/src/pics/hi48-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..adb26a0 --- /dev/null +++ b/src/pics/hi48-action-kdesvncleanup.png diff --git a/src/pics/hi48-action-kdesvncommit.png b/src/pics/hi48-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..31dbaac --- /dev/null +++ b/src/pics/hi48-action-kdesvncommit.png diff --git a/src/pics/hi48-action-kdesvncopy.png b/src/pics/hi48-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..47b2e03 --- /dev/null +++ b/src/pics/hi48-action-kdesvncopy.png diff --git a/src/pics/hi48-action-kdesvndelete.png b/src/pics/hi48-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..7834b7b --- /dev/null +++ b/src/pics/hi48-action-kdesvndelete.png diff --git a/src/pics/hi48-action-kdesvndiff.png b/src/pics/hi48-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..22f52a9 --- /dev/null +++ b/src/pics/hi48-action-kdesvndiff.png diff --git a/src/pics/hi48-action-kdesvnexport.png b/src/pics/hi48-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..bc54b0a --- /dev/null +++ b/src/pics/hi48-action-kdesvnexport.png diff --git a/src/pics/hi48-action-kdesvninfo.png b/src/pics/hi48-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..1782950 --- /dev/null +++ b/src/pics/hi48-action-kdesvninfo.png diff --git a/src/pics/hi48-action-kdesvnlock.png b/src/pics/hi48-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..6c9c400 --- /dev/null +++ b/src/pics/hi48-action-kdesvnlock.png diff --git a/src/pics/hi48-action-kdesvnlog.png b/src/pics/hi48-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..86b6d22 --- /dev/null +++ b/src/pics/hi48-action-kdesvnlog.png diff --git a/src/pics/hi48-action-kdesvnmerge.png b/src/pics/hi48-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..e2a8be2 --- /dev/null +++ b/src/pics/hi48-action-kdesvnmerge.png diff --git a/src/pics/hi48-action-kdesvnrelocate.png b/src/pics/hi48-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..99a601e --- /dev/null +++ b/src/pics/hi48-action-kdesvnrelocate.png diff --git a/src/pics/hi48-action-kdesvnswitch.png b/src/pics/hi48-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..9caec56 --- /dev/null +++ b/src/pics/hi48-action-kdesvnswitch.png diff --git a/src/pics/hi48-action-kdesvnunlock.png b/src/pics/hi48-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..afe7eb9 --- /dev/null +++ b/src/pics/hi48-action-kdesvnunlock.png diff --git a/src/pics/hi48-action-kdesvnupdate.png b/src/pics/hi48-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..ef774d9 --- /dev/null +++ b/src/pics/hi48-action-kdesvnupdate.png diff --git a/src/pics/hi48-filesys-kdesvnadded.png b/src/pics/hi48-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..091847e --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnadded.png diff --git a/src/pics/hi48-filesys-kdesvnconflicted.png b/src/pics/hi48-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..567220a --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnconflicted.png diff --git a/src/pics/hi48-filesys-kdesvndeleted.png b/src/pics/hi48-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..054198b --- /dev/null +++ b/src/pics/hi48-filesys-kdesvndeleted.png diff --git a/src/pics/hi48-filesys-kdesvnlocked.png b/src/pics/hi48-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..1f03a17 --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnlocked.png diff --git a/src/pics/hi48-filesys-kdesvnmodified.png b/src/pics/hi48-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..f2d14ac --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnmodified.png diff --git a/src/pics/hi48-filesys-kdesvnneedlock.png b/src/pics/hi48-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..929bd41 --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnneedlock.png diff --git a/src/pics/hi48-filesys-kdesvnupdates.png b/src/pics/hi48-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..76db01b --- /dev/null +++ b/src/pics/hi48-filesys-kdesvnupdates.png diff --git a/src/pics/hi64-action-kdesvnadd.png b/src/pics/hi64-action-kdesvnadd.png Binary files differnew file mode 100644 index 0000000..72341d5 --- /dev/null +++ b/src/pics/hi64-action-kdesvnadd.png diff --git a/src/pics/hi64-action-kdesvnaddrecursive.png b/src/pics/hi64-action-kdesvnaddrecursive.png Binary files differnew file mode 100644 index 0000000..4654b01 --- /dev/null +++ b/src/pics/hi64-action-kdesvnaddrecursive.png diff --git a/src/pics/hi64-action-kdesvnblame.png b/src/pics/hi64-action-kdesvnblame.png Binary files differnew file mode 100644 index 0000000..a428530 --- /dev/null +++ b/src/pics/hi64-action-kdesvnblame.png diff --git a/src/pics/hi64-action-kdesvncat.png b/src/pics/hi64-action-kdesvncat.png Binary files differnew file mode 100644 index 0000000..e9c404b --- /dev/null +++ b/src/pics/hi64-action-kdesvncat.png diff --git a/src/pics/hi64-action-kdesvncheckout.png b/src/pics/hi64-action-kdesvncheckout.png Binary files differnew file mode 100644 index 0000000..9d17392 --- /dev/null +++ b/src/pics/hi64-action-kdesvncheckout.png diff --git a/src/pics/hi64-action-kdesvncheckupdates.png b/src/pics/hi64-action-kdesvncheckupdates.png Binary files differnew file mode 100644 index 0000000..f9c34fb --- /dev/null +++ b/src/pics/hi64-action-kdesvncheckupdates.png diff --git a/src/pics/hi64-action-kdesvncleanup.png b/src/pics/hi64-action-kdesvncleanup.png Binary files differnew file mode 100644 index 0000000..48a6018 --- /dev/null +++ b/src/pics/hi64-action-kdesvncleanup.png diff --git a/src/pics/hi64-action-kdesvncommit.png b/src/pics/hi64-action-kdesvncommit.png Binary files differnew file mode 100644 index 0000000..00053d3 --- /dev/null +++ b/src/pics/hi64-action-kdesvncommit.png diff --git a/src/pics/hi64-action-kdesvncopy.png b/src/pics/hi64-action-kdesvncopy.png Binary files differnew file mode 100644 index 0000000..36f3a4a --- /dev/null +++ b/src/pics/hi64-action-kdesvncopy.png diff --git a/src/pics/hi64-action-kdesvndelete.png b/src/pics/hi64-action-kdesvndelete.png Binary files differnew file mode 100644 index 0000000..69d97e4 --- /dev/null +++ b/src/pics/hi64-action-kdesvndelete.png diff --git a/src/pics/hi64-action-kdesvndiff.png b/src/pics/hi64-action-kdesvndiff.png Binary files differnew file mode 100644 index 0000000..229ab6a --- /dev/null +++ b/src/pics/hi64-action-kdesvndiff.png diff --git a/src/pics/hi64-action-kdesvnexport.png b/src/pics/hi64-action-kdesvnexport.png Binary files differnew file mode 100644 index 0000000..f9fa9de --- /dev/null +++ b/src/pics/hi64-action-kdesvnexport.png diff --git a/src/pics/hi64-action-kdesvninfo.png b/src/pics/hi64-action-kdesvninfo.png Binary files differnew file mode 100644 index 0000000..13f151b --- /dev/null +++ b/src/pics/hi64-action-kdesvninfo.png diff --git a/src/pics/hi64-action-kdesvnlock.png b/src/pics/hi64-action-kdesvnlock.png Binary files differnew file mode 100644 index 0000000..efd5637 --- /dev/null +++ b/src/pics/hi64-action-kdesvnlock.png diff --git a/src/pics/hi64-action-kdesvnlog.png b/src/pics/hi64-action-kdesvnlog.png Binary files differnew file mode 100644 index 0000000..931737a --- /dev/null +++ b/src/pics/hi64-action-kdesvnlog.png diff --git a/src/pics/hi64-action-kdesvnmerge.png b/src/pics/hi64-action-kdesvnmerge.png Binary files differnew file mode 100644 index 0000000..7481273 --- /dev/null +++ b/src/pics/hi64-action-kdesvnmerge.png diff --git a/src/pics/hi64-action-kdesvnrelocate.png b/src/pics/hi64-action-kdesvnrelocate.png Binary files differnew file mode 100644 index 0000000..f4e4d84 --- /dev/null +++ b/src/pics/hi64-action-kdesvnrelocate.png diff --git a/src/pics/hi64-action-kdesvnswitch.png b/src/pics/hi64-action-kdesvnswitch.png Binary files differnew file mode 100644 index 0000000..75af830 --- /dev/null +++ b/src/pics/hi64-action-kdesvnswitch.png diff --git a/src/pics/hi64-action-kdesvnunlock.png b/src/pics/hi64-action-kdesvnunlock.png Binary files differnew file mode 100644 index 0000000..e720d73 --- /dev/null +++ b/src/pics/hi64-action-kdesvnunlock.png diff --git a/src/pics/hi64-action-kdesvnupdate.png b/src/pics/hi64-action-kdesvnupdate.png Binary files differnew file mode 100644 index 0000000..3b025e2 --- /dev/null +++ b/src/pics/hi64-action-kdesvnupdate.png diff --git a/src/pics/hi64-filesys-kdesvnadded.png b/src/pics/hi64-filesys-kdesvnadded.png Binary files differnew file mode 100644 index 0000000..b6c4e30 --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnadded.png diff --git a/src/pics/hi64-filesys-kdesvnconflicted.png b/src/pics/hi64-filesys-kdesvnconflicted.png Binary files differnew file mode 100644 index 0000000..10dec3b --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnconflicted.png diff --git a/src/pics/hi64-filesys-kdesvndeleted.png b/src/pics/hi64-filesys-kdesvndeleted.png Binary files differnew file mode 100644 index 0000000..16691a0 --- /dev/null +++ b/src/pics/hi64-filesys-kdesvndeleted.png diff --git a/src/pics/hi64-filesys-kdesvnlocked.png b/src/pics/hi64-filesys-kdesvnlocked.png Binary files differnew file mode 100644 index 0000000..e358002 --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnlocked.png diff --git a/src/pics/hi64-filesys-kdesvnmodified.png b/src/pics/hi64-filesys-kdesvnmodified.png Binary files differnew file mode 100644 index 0000000..a0d5999 --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnmodified.png diff --git a/src/pics/hi64-filesys-kdesvnneedlock.png b/src/pics/hi64-filesys-kdesvnneedlock.png Binary files differnew file mode 100644 index 0000000..cdf9904 --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnneedlock.png diff --git a/src/pics/hi64-filesys-kdesvnupdates.png b/src/pics/hi64-filesys-kdesvnupdates.png Binary files differnew file mode 100644 index 0000000..bcfa69e --- /dev/null +++ b/src/pics/hi64-filesys-kdesvnupdates.png diff --git a/src/pics/hisc-action-kdesvnadd.svgz b/src/pics/hisc-action-kdesvnadd.svgz Binary files differnew file mode 100644 index 0000000..881ef7b --- /dev/null +++ b/src/pics/hisc-action-kdesvnadd.svgz diff --git a/src/pics/hisc-action-kdesvnaddrecursive.svgz b/src/pics/hisc-action-kdesvnaddrecursive.svgz Binary files differnew file mode 100644 index 0000000..423f80c --- /dev/null +++ b/src/pics/hisc-action-kdesvnaddrecursive.svgz diff --git a/src/pics/hisc-action-kdesvnblame.svgz b/src/pics/hisc-action-kdesvnblame.svgz Binary files differnew file mode 100644 index 0000000..13ccb93 --- /dev/null +++ b/src/pics/hisc-action-kdesvnblame.svgz diff --git a/src/pics/hisc-action-kdesvncat.svgz b/src/pics/hisc-action-kdesvncat.svgz Binary files differnew file mode 100644 index 0000000..fab8004 --- /dev/null +++ b/src/pics/hisc-action-kdesvncat.svgz diff --git a/src/pics/hisc-action-kdesvncheckout.svgz b/src/pics/hisc-action-kdesvncheckout.svgz Binary files differnew file mode 100644 index 0000000..49f39bd --- /dev/null +++ b/src/pics/hisc-action-kdesvncheckout.svgz diff --git a/src/pics/hisc-action-kdesvncheckupdates.svgz b/src/pics/hisc-action-kdesvncheckupdates.svgz Binary files differnew file mode 100644 index 0000000..604cbad --- /dev/null +++ b/src/pics/hisc-action-kdesvncheckupdates.svgz diff --git a/src/pics/hisc-action-kdesvncleanup.svgz b/src/pics/hisc-action-kdesvncleanup.svgz Binary files differnew file mode 100644 index 0000000..109ad5e --- /dev/null +++ b/src/pics/hisc-action-kdesvncleanup.svgz diff --git a/src/pics/hisc-action-kdesvncommit.svgz b/src/pics/hisc-action-kdesvncommit.svgz Binary files differnew file mode 100644 index 0000000..8bb7993 --- /dev/null +++ b/src/pics/hisc-action-kdesvncommit.svgz diff --git a/src/pics/hisc-action-kdesvncopy.svgz b/src/pics/hisc-action-kdesvncopy.svgz Binary files differnew file mode 100644 index 0000000..7ecfae2 --- /dev/null +++ b/src/pics/hisc-action-kdesvncopy.svgz diff --git a/src/pics/hisc-action-kdesvndelete.svgz b/src/pics/hisc-action-kdesvndelete.svgz Binary files differnew file mode 100644 index 0000000..9445c91 --- /dev/null +++ b/src/pics/hisc-action-kdesvndelete.svgz diff --git a/src/pics/hisc-action-kdesvndiff.svgz b/src/pics/hisc-action-kdesvndiff.svgz Binary files differnew file mode 100644 index 0000000..b1e0a58 --- /dev/null +++ b/src/pics/hisc-action-kdesvndiff.svgz diff --git a/src/pics/hisc-action-kdesvnexport.svgz b/src/pics/hisc-action-kdesvnexport.svgz Binary files differnew file mode 100644 index 0000000..b692125 --- /dev/null +++ b/src/pics/hisc-action-kdesvnexport.svgz diff --git a/src/pics/hisc-action-kdesvninfo.svgz b/src/pics/hisc-action-kdesvninfo.svgz Binary files differnew file mode 100644 index 0000000..399ea3d --- /dev/null +++ b/src/pics/hisc-action-kdesvninfo.svgz diff --git a/src/pics/hisc-action-kdesvnlock.svgz b/src/pics/hisc-action-kdesvnlock.svgz Binary files differnew file mode 100644 index 0000000..3021475 --- /dev/null +++ b/src/pics/hisc-action-kdesvnlock.svgz diff --git a/src/pics/hisc-action-kdesvnlog.svgz b/src/pics/hisc-action-kdesvnlog.svgz Binary files differnew file mode 100644 index 0000000..59d343b --- /dev/null +++ b/src/pics/hisc-action-kdesvnlog.svgz diff --git a/src/pics/hisc-action-kdesvnmerge.svgz b/src/pics/hisc-action-kdesvnmerge.svgz Binary files differnew file mode 100644 index 0000000..0750deb --- /dev/null +++ b/src/pics/hisc-action-kdesvnmerge.svgz diff --git a/src/pics/hisc-action-kdesvnrelocate.svgz b/src/pics/hisc-action-kdesvnrelocate.svgz Binary files differnew file mode 100644 index 0000000..280f24d --- /dev/null +++ b/src/pics/hisc-action-kdesvnrelocate.svgz diff --git a/src/pics/hisc-action-kdesvnswitch.svgz b/src/pics/hisc-action-kdesvnswitch.svgz Binary files differnew file mode 100644 index 0000000..164e7ca --- /dev/null +++ b/src/pics/hisc-action-kdesvnswitch.svgz diff --git a/src/pics/hisc-action-kdesvnunlock.svgz b/src/pics/hisc-action-kdesvnunlock.svgz Binary files differnew file mode 100644 index 0000000..e05e5d5 --- /dev/null +++ b/src/pics/hisc-action-kdesvnunlock.svgz diff --git a/src/pics/hisc-action-kdesvnupdate.svgz b/src/pics/hisc-action-kdesvnupdate.svgz Binary files differnew file mode 100644 index 0000000..f3976aa --- /dev/null +++ b/src/pics/hisc-action-kdesvnupdate.svgz diff --git a/src/pics/hisc-filesys-kdesvnadded.svgz b/src/pics/hisc-filesys-kdesvnadded.svgz Binary files differnew file mode 100644 index 0000000..d78c077 --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnadded.svgz diff --git a/src/pics/hisc-filesys-kdesvnconflicted.svgz b/src/pics/hisc-filesys-kdesvnconflicted.svgz Binary files differnew file mode 100644 index 0000000..7484329 --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnconflicted.svgz diff --git a/src/pics/hisc-filesys-kdesvndeleted.svgz b/src/pics/hisc-filesys-kdesvndeleted.svgz Binary files differnew file mode 100644 index 0000000..e6dd90a --- /dev/null +++ b/src/pics/hisc-filesys-kdesvndeleted.svgz diff --git a/src/pics/hisc-filesys-kdesvnlocked.svgz b/src/pics/hisc-filesys-kdesvnlocked.svgz Binary files differnew file mode 100644 index 0000000..67bcb72 --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnlocked.svgz diff --git a/src/pics/hisc-filesys-kdesvnmodified.svgz b/src/pics/hisc-filesys-kdesvnmodified.svgz Binary files differnew file mode 100644 index 0000000..34eb9a2 --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnmodified.svgz diff --git a/src/pics/hisc-filesys-kdesvnneedlock.svgz b/src/pics/hisc-filesys-kdesvnneedlock.svgz Binary files differnew file mode 100644 index 0000000..5813b6c --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnneedlock.svgz diff --git a/src/pics/hisc-filesys-kdesvnupdates.svgz b/src/pics/hisc-filesys-kdesvnupdates.svgz Binary files differnew file mode 100644 index 0000000..1e76059 --- /dev/null +++ b/src/pics/hisc-filesys-kdesvnupdates.svgz diff --git a/src/pics/to_png.py b/src/pics/to_png.py new file mode 100755 index 0000000..5968fd1 --- /dev/null +++ b/src/pics/to_png.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +import os + +def convert(file, px): + new_file=file.replace('.svgz','.png').replace('.svg','.png').replace('hisc-','') + os.system('/usr/bin/inkscape -e hicolor/hi%s-%s -w %s -h %s %s' % (px, new_file, px, px, file)) + +all_files=[ +'hisc-action-kdesvnaddrecursive.svgz', +'hisc-action-kdesvnadd.svgz', +'hisc-action-kdesvnblame.svgz', +'hisc-action-kdesvncat.svgz', +'hisc-action-kdesvncheckout.svgz', +'hisc-action-kdesvncheckupdates.svgz', +'hisc-action-kdesvncleanup.svgz', +'hisc-action-kdesvncommit.svgz', +'hisc-action-kdesvncopy.svgz', +'hisc-action-kdesvndelete.svgz', +'hisc-action-kdesvndiff.svgz', +'hisc-action-kdesvnexport.svgz', +'hisc-action-kdesvninfo.svgz', +'hisc-action-kdesvnlock.svgz', +'hisc-action-kdesvnlog.svgz', +'hisc-action-kdesvnmerge.svgz', +'hisc-action-kdesvnrelocate.svgz', +'hisc-action-kdesvnswitch.svgz', +'hisc-action-kdesvnunlock.svgz', +'hisc-action-kdesvnupdate.svgz', +'hisc-filesys-kdesvnadded.svgz', +'hisc-filesys-kdesvnconflicted.svgz', +'hisc-filesys-kdesvndeleted.svgz', +'hisc-filesys-kdesvnlocked.svgz', +'hisc-filesys-kdesvnmodified.svgz', +'hisc-filesys-kdesvnupdates.svgz', +'hisc-filesys-kdesvnneedlock.svgz', +] + +i_sizes=[ +32,128,16,96,22,48,64] + +i_sizes.sort() + +for px in i_sizes: + os.system('mkdir -p hicolor/%sx%s/actions' % (px,px)) + os.system('mkdir -p hicolor/%sx%s/filesystems' % (px,px)) + +for file in all_files: + for px in i_sizes: + convert(file, px) diff --git a/src/settings/CMakeLists.txt b/src/settings/CMakeLists.txt new file mode 100644 index 0000000..fb1cd60 --- /dev/null +++ b/src/settings/CMakeLists.txt @@ -0,0 +1,50 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + +KDE3_ADD_KCFG_FILES(cfgsrc + kdesvnsettings.kcfgc) +ADD_LIBRARY(kdesvncfgreader STATIC ${cfgsrc}) + +KDE3_ADD_UI_FILES( + settings_ui_sources + dispcolor_settings.ui + display_settings.ui + revisiontree_settings.ui + subversion_settings.ui + cmdexecsettings.ui + diffmergesettings.ui +) + +SET(settings_sources + dispcolorsettings_impl.cpp + displaysettings_impl.cpp + revisiontreesettingsdlg_impl.cpp + subversionsettings_impl.cpp + cmdexecsettings_impl.cpp + diffmergesettings_impl.cpp) + +FILE(GLOB hdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") + +KDE3_AUTOMOC(${settings_sources}) +ADD_LIBRARY(settingsdlgs STATIC ${settings_ui_sources} ${settings_sources} ${hdr}) +ADD_DEPENDENCIES(settingsdlgs kdesvncfgreader) + +SET_TARGET_PROPERTIES(kdesvncfgreader settingsdlgs + PROPERTIES + COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/kdesvn_part.kcfg DESTINATION ${KCFG_INSTALL_DIR}) + +INSTALL( + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/kdesvnpartrc-use-external.upd + DESTINATION + ${DATA_INSTALL_DIR}/kconf_update +) + +INSTALL( + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/kdesvn-use-external-update.sh + DESTINATION + ${DATA_INSTALL_DIR}/kconf_update + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ +) diff --git a/src/settings/cmdexecsettings.ui b/src/settings/cmdexecsettings.ui new file mode 100644 index 0000000..e2b4a4e --- /dev/null +++ b/src/settings/cmdexecsettings.ui @@ -0,0 +1,155 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CmdExecSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CmdExecSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>323</width> + <height>163</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_cmdline_show_logwindow</cstring> + </property> + <property name="text"> + <string>Show log after executing a command</string> + </property> + <property name="toolTip" stdset="0"> + <string>Show a small window containing the log after command executed</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Minimum log lines to show:</string> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>kcfg_cmdline_log_minline</cstring> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="suffix"> + <string> line(s)</string> + </property> + <property name="specialValueText"> + <string>0</string> + <comment>no limit</comment> + </property> + <property name="toolTip" stdset="0"> + <string>The minimum a log output must contain before kdesvn shows a single logwindow</string> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_no_konqueror_contextmenu</cstring> + </property> + <property name="text"> + <string>Don't display contextmenu in Konqueror</string> + </property> + <property name="toolTip" stdset="0"> + <string>If set, kdesvn will not show a menu inside "Action" menu of konqueror</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_kio_use_standard_logmsg</cstring> + </property> + <property name="text"> + <string>KIO operations use standard logmessage</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_kio_standard_logmsg</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>stdLogmsgLabel</cstring> + </property> + <property name="text"> + <string>Standard message:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_kio_use_standard_logmsg</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_kio_standard_logmsg</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_cmdline_show_logwindow</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_cmdline_log_minline</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<slots> + <slot access="protected">showLogToggled(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/src/settings/cmdexecsettings_impl.cpp b/src/settings/cmdexecsettings_impl.cpp new file mode 100644 index 0000000..94f4f3d --- /dev/null +++ b/src/settings/cmdexecsettings_impl.cpp @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "cmdexecsettings_impl.h" + +#include <klocale.h> +#include <knuminput.h> +#include <qcheckbox.h> +#include <klineedit.h> + +CmdExecSettings_impl::CmdExecSettings_impl(QWidget* parent, const char* name, WFlags fl) +: CmdExecSettings(parent,name,fl) +{ + kcfg_cmdline_log_minline->setSpecialValueText(i18n("No minimum")); + kcfg_cmdline_log_minline->setEnabled(kcfg_cmdline_show_logwindow->isChecked()); + kcfg_kio_standard_logmsg->setEnabled(kcfg_kio_use_standard_logmsg->isChecked()); +} + +CmdExecSettings_impl::~CmdExecSettings_impl() +{ +} + +#include "cmdexecsettings_impl.moc" diff --git a/src/settings/cmdexecsettings_impl.h b/src/settings/cmdexecsettings_impl.h new file mode 100644 index 0000000..ab1749b --- /dev/null +++ b/src/settings/cmdexecsettings_impl.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef CMDEXECSETTINGS_IMPL_H +#define CMDEXECSETTINGS_IMPL_H + +#include "src/settings/cmdexecsettings.h" + +class CmdExecSettings_impl : public CmdExecSettings +{ + Q_OBJECT + +public: + CmdExecSettings_impl(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~CmdExecSettings_impl(); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + +protected: + +protected slots: + /*$PROTECTED_SLOTS$*/ + +}; + +#endif + diff --git a/src/settings/diffmergesettings.ui b/src/settings/diffmergesettings.ui new file mode 100644 index 0000000..07638a0 --- /dev/null +++ b/src/settings/diffmergesettings.ui @@ -0,0 +1,251 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DiffMergeSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DiffMergeSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>260</width> + <height>308</height> + </rect> + </property> + <property name="caption"> + <string>DiffMergeSettings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_diff_ignore_content</cstring> + </property> + <property name="text"> + <string>Diff ignores content type</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_tree_diff_rec</cstring> + </property> + <property name="text"> + <string>Diff in revisiontree is recursive</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_diff_ignore_spaces</cstring> + </property> + <property name="text"> + <string>Diff ignores white space changes</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_diff_ignore_all_white_spaces</cstring> + </property> + <property name="text"> + <string>Diff ignores all white spaces</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_use_external_diff</cstring> + </property> + <property name="text"> + <string>Use external diff display</string> + </property> + <property name="toolTip" stdset="0"> + <string>If kdesvn should use an external diff display and/or generator. If not checked use internal display.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_extern_merge_default</cstring> + </property> + <property name="text"> + <string>Prefer external merge program</string> + </property> + <property name="toolTip" stdset="0"> + <string>Set if merge with external program is prefered and not subversions merge</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_extern_hint</cstring> + </property> + <property name="text"> + <string>see "Whats this" for details</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignCenter</set> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>resolveLabel</cstring> + </property> + <property name="text"> + <string>Conflict resolver program:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>External merge program:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_conflict_resolver</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>Setup an external program for conflict resolving</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p> +Enter how kdesvn should call the conflict resolver program. The form is +<p align="center"> +<b><tt>&lt;program&gt; &lt;programoptions&gt;</tt></b> +</p> +<p> +Programoption may contain the place holders for substituting with filenames. +</p> +The substitutions means:<br> +<b><tt>%o</tt></b> Old version<br> +<b><tt>%m</tt></b> Mine or local edit version<br> +<b><tt>%n</tt></b> Newest version<br> +<b><tt>%t</tt></b> The target to save as, kdesvn will use the orignal file name for it. +</p> +<p> +Default: <tt>kdiff3 %o %m %n -o %t</tt> +</p></string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>mdiff_display_label</cstring> + </property> + <property name="text"> + <string>External diff display:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_external_merge_program</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>Setup an external program for merging</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p> +Enter how kdesvn should call the external merge program. The form is +<p align="center"> +<b><tt>&lt;program&gt; &lt;programoptions&gt; %s1 %s2 %t</tt></b> +</p> +The substitutions means:<br> +<b><tt>%s1</tt></b> Source one for merge<br> +<b><tt>%s2</tt></b> Source two for merge, if it was not set equal to source one but other revision<br> +<b><tt>%t</tt></b> Local target for merge. +</p></string> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_external_diff_display</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><p align="left"> +Enter an external program in form +<p align="center"> +<tt>&lt;program&gt; &lt;param&gt; %f</tt> +</p> +or +<p align="center"> +<tt>&lt;program&gt; &lt;param&gt;</tt> +</p> +or +<p align="center"> +<tt>&lt;program&gt; &lt;param&gt; %1 %2</tt> +</p> +<br> +If using first or second form, svn itself will generate the diff. %f will replaced with a temporary filename. If %f is not given, +the diff-display should able reading data from stdin. +<br> +When %1 and %2 is given, kdesvn let this display make the diff. For that it it makes a temporary export or get (if needed) and fill out the parameters with the right value. %1 will filled with the content of start-revision, %2 with the endrevision. On large recoursive diffs this may get real slow! +</p></string> + </property> + </widget> + </grid> + </widget> + </grid> + </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>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_use_external_diff</sender> + <signal>toggled(bool)</signal> + <receiver>DiffMergeSettings</receiver> + <slot>diffDispChanged(bool)</slot> + </connection> +</connections> +<slots> + <slot access="protected">diffDispChanged(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/src/settings/diffmergesettings_impl.cpp b/src/settings/diffmergesettings_impl.cpp new file mode 100644 index 0000000..91ddab3 --- /dev/null +++ b/src/settings/diffmergesettings_impl.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "diffmergesettings_impl.h" +#include "src/settings/kdesvnsettings.h" + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <klineedit.h> +#include <kdebug.h> + +DiffMergeSettings_impl::DiffMergeSettings_impl(QWidget *parent, const char *name) + :DiffMergeSettings(parent, name) +{ + kcfg_external_diff_display->setEnabled(Kdesvnsettings::use_external_diff()); +} + +DiffMergeSettings_impl::~DiffMergeSettings_impl() +{ +} + +void DiffMergeSettings_impl::diffDispChanged(bool how) +{ + kcfg_external_diff_display->setEnabled(how); +} + +#include "diffmergesettings_impl.moc" + diff --git a/src/settings/diffmergesettings_impl.h b/src/settings/diffmergesettings_impl.h new file mode 100644 index 0000000..639e38b --- /dev/null +++ b/src/settings/diffmergesettings_impl.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DIFFMERGESETTINGS_IMPL_H +#define DIFFMERGESETTINGS_IMPL_H + +#include "src/settings/diffmergesettings.h" + +class DiffMergeSettings_impl: public DiffMergeSettings { +Q_OBJECT +public: + DiffMergeSettings_impl(QWidget *parent = 0, const char *name = 0); + virtual ~DiffMergeSettings_impl(); +protected slots: + virtual void diffDispChanged(bool); +}; + +#endif diff --git a/src/settings/dispcolor_settings.ui b/src/settings/dispcolor_settings.ui new file mode 100644 index 0000000..c5118ba --- /dev/null +++ b/src/settings/dispcolor_settings.ui @@ -0,0 +1,259 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DispColorSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ColorSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>264</width> + <height>325</height> + </rect> + </property> + <property name="caption"> + <string>ColorSettings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_colored_state</cstring> + </property> + <property name="text"> + <string>Mark changed and locked items colored</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KColorButton" row="8" column="1"> + <property name="name"> + <cstring>kcfg_color_conflicted_item</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>kcfg_color_changed_item</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="2" column="1"> + <property name="name"> + <cstring>kcfg_color_item_added</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Locked items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton" row="3" column="1"> + <property name="name"> + <cstring>kcfg_color_item_deleted</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="7" column="0"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string>Not versioned items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Remote changed items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Added items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Deleted items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton" row="5" column="1"> + <property name="name"> + <cstring>kcfg_color_need_lock</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="6" column="1"> + <property name="name"> + <cstring>kcfg_color_missed_item</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="4" column="1"> + <property name="name"> + <cstring>kcfg_color_locked_item</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="7" column="1"> + <property name="name"> + <cstring>kcfg_color_notversioned_item</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="8" column="0"> + <property name="name"> + <cstring>Conflicted_items_label</cstring> + </property> + <property name="text"> + <string>Conflicted items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>Missed_items_label</cstring> + </property> + <property name="text"> + <string>Missed items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Local changed items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>Need_lock_label_2</cstring> + </property> + <property name="text"> + <string>Item needs lock:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>kcfg_color_need_update</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>kcfg_colored_state</sender> + <signal>toggled(bool)</signal> + <receiver>ColorSettings</receiver> + <slot>coloredStateToggled(bool)</slot> + </connection> +</connections> +<slots> + <slot access="protected">coloredStateToggled(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/src/settings/dispcolorsettings_impl.cpp b/src/settings/dispcolorsettings_impl.cpp new file mode 100644 index 0000000..1b3ad0c --- /dev/null +++ b/src/settings/dispcolorsettings_impl.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "dispcolorsettings_impl.h" +#include <kcolorbutton.h> +#include <qcheckbox.h> + +DispColorSettings_impl::DispColorSettings_impl(QWidget *parent, const char *name) + :DispColorSettings(parent, name) +{ + coloredStateToggled(kcfg_colored_state->isChecked()); +} + +DispColorSettings_impl::~DispColorSettings_impl() +{ +} + +void DispColorSettings_impl::coloredStateToggled(bool how) +{ + kcfg_color_locked_item->setEnabled(how); + kcfg_color_changed_item->setEnabled(how); + kcfg_color_item_deleted->setEnabled(how); + kcfg_color_item_added->setEnabled(how); + kcfg_color_need_update->setEnabled(how); + kcfg_color_missed_item->setEnabled(how); + kcfg_color_notversioned_item->setEnabled(how); + kcfg_color_conflicted_item->setEnabled(how); +} + + +#include "dispcolorsettings_impl.moc" diff --git a/src/settings/dispcolorsettings_impl.h b/src/settings/dispcolorsettings_impl.h new file mode 100644 index 0000000..56e0edd --- /dev/null +++ b/src/settings/dispcolorsettings_impl.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DISPCOLORSETTINGS_IMPL_H +#define DISPCOLORSETTINGS_IMPL_H + +#include "src/settings/dispcolor_settings.h" + +class DispColorSettings_impl: public DispColorSettings { +Q_OBJECT +public: + DispColorSettings_impl(QWidget *parent = 0, const char *name = 0); + virtual ~DispColorSettings_impl(); +protected slots: + virtual void coloredStateToggled(bool); +}; + +#endif diff --git a/src/settings/display_settings.ui b/src/settings/display_settings.ui new file mode 100644 index 0000000..f3dfe98 --- /dev/null +++ b/src/settings/display_settings.ui @@ -0,0 +1,243 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DisplaySettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DisplaySettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>280</width> + <height>295</height> + </rect> + </property> + <property name="caption"> + <string>Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_ListIconsSize_label</cstring> + </property> + <property name="text"> + <string>Size of Listviewicons</string> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_listview_icon_size</cstring> + </property> + <property name="maxValue"> + <number>128</number> + </property> + <property name="minValue"> + <number>16</number> + </property> + <property name="value"> + <number>22</number> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_display_file_tips</cstring> + </property> + <property name="text"> + <string>Show file info</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Here you can control if, when moving the mouse over a file, you want to see a small popup window with additional information about that file</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_display_previews_in_file_tips</cstring> + </property> + <property name="text"> + <string>Display previews in file tips</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Here you can control if you want the popup window to contain a larger preview for the file, when moving the mouse over it</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_display_overlays</cstring> + </property> + <property name="text"> + <string>Mark item status with icon overlay</string> + </property> + <property name="toolTip" stdset="0"> + <string>Mark subversion states with an overlayed icon</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p align="left"> +Mark an items with non-normal state with an overlayed icon. When you wish to +see which items has newer items in repository you may have to set "Check for updates on open" in Subversion-Dialog. +</p></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_case_sensitive_sort</cstring> + </property> + <property name="text"> + <string>Items sortorder is case sensitive</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_display_ignored_files</cstring> + </property> + <property name="text"> + <string>Display ignored files</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_start_log_cache_on_open</cstring> + </property> + <property name="text"> + <string>Automatic update of logcache</string> + </property> + <property name="toolTip" stdset="0"> + <string>If set start filling the logcache when open a repository or working copy</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Set if the internal logcache should updated after open a working copy or repository or after a commit in a working copy. + +If networking is disabled, then this flag is ignored.</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2_2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_display_label</cstring> + </property> + <property name="text"> + <string>External display:</string> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_external_display</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><p align="left"> +Enter an external program for opening file on doubleclick in form +<br> +<tt>&lt;program&gt;</tt> +</p> +<p> +When kde-default is wanted for opening on double click, enter &quot;default&quot; and kde selects action. +</p></string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_MaxLogLabel</cstring> + </property> + <property name="text"> + <string>Maximum logmessages in history:</string> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_max_log_messages</cstring> + </property> + <property name="maxValue"> + <number>150</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_colored_blame</cstring> + </property> + <property name="text"> + <string>Display colored annotate</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>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_display_file_tips</sender> + <signal>toggled(bool)</signal> + <receiver>DisplaySettings</receiver> + <slot>dispFileInfotoggled(bool)</slot> + </connection> + <connection> + <sender>kcfg_external_display</sender> + <signal>selectionChanged()</signal> + <receiver>DisplaySettings</receiver> + <slot>diffDispChanged()</slot> + </connection> +</connections> +<slots> + <slot access="protected">diffDispChanged()</slot> + <slot access="protected">dispFileInfotoggled(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/src/settings/displaysettings_impl.cpp b/src/settings/displaysettings_impl.cpp new file mode 100644 index 0000000..3f4e79c --- /dev/null +++ b/src/settings/displaysettings_impl.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "displaysettings_impl.h" +#include "src/settings/kdesvnsettings.h" + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <klineedit.h> +#include <kdebug.h> + +DisplaySettings_impl::DisplaySettings_impl(QWidget *parent, const char *name) + :DisplaySettings(parent, name) +{ + kcfg_display_previews_in_file_tips->setEnabled(kcfg_display_file_tips->isChecked()); +} + +DisplaySettings_impl::~DisplaySettings_impl() +{ +} + +void DisplaySettings_impl::dispFileInfotoggled(bool how) +{ + kcfg_display_previews_in_file_tips->setEnabled(how); +} + +#include "displaysettings_impl.moc" diff --git a/src/settings/displaysettings_impl.h b/src/settings/displaysettings_impl.h new file mode 100644 index 0000000..944333e --- /dev/null +++ b/src/settings/displaysettings_impl.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DISPLAYSETTINGS_IMPL_H +#define DISPLAYSETTINGS_IMPL_H + +#include "src/settings/display_settings.h" + +class DisplaySettings_impl: public DisplaySettings { +Q_OBJECT +public: + DisplaySettings_impl(QWidget *parent = 0, const char *name = 0); + virtual ~DisplaySettings_impl(); +protected slots: + virtual void dispFileInfotoggled(bool); +}; + +#endif diff --git a/src/settings/kdesvn-use-external-update.sh b/src/settings/kdesvn-use-external-update.sh new file mode 100755 index 0000000..c97242a --- /dev/null +++ b/src/settings/kdesvn-use-external-update.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +display= +lastvalue= + +while read line ; do + if [ "${line#\[}" != "$line" ]; then + continue; + fi + KEY="${line%%=*}" + VALUE="${line#*=}" + if echo "$KEY" | grep 'use_kompare_for_diff' >/dev/null 2>/dev/null; then + display=$VALUE + echo '# DELETE [general_items]use_kompare_for_diff' + elif echo "$KEY" | grep 'external_diff_display' > /dev/null 2>/dev/null; then + exdisplay=$VALUE + elif [ "x$KEY" != "x" ]; then + echo "$KEY=$VALUE" + fi +done + +if [ "x$exdisplay" = "x" -o "x$display" = "x1" ]; then + exdisplay="kompare -on -" +fi +if [ "x$display" = "x2" -o "x$display" = "x1" ]; then + display=true +else + display=false +fi +echo "use_external_diff=$display" +echo "external_diff_display=$exdisplay" diff --git a/src/settings/kdesvn_part.kcfg b/src/settings/kdesvn_part.kcfg new file mode 100644 index 0000000..382ddde --- /dev/null +++ b/src/settings/kdesvn_part.kcfg @@ -0,0 +1,261 @@ +<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd"> +<kcfg> + <kcfgfile name="kdesvnpartrc" /> + <include>qstring.h</include> + <group name="general_items" > + <entry key="case_sensitive_sort" type="Bool" > + <label>Set if items sortorder should be case sensitive or not</label> + <default>true</default> + </entry> + <entry key="listview_icon_size" type="Int" > + <label>Size of the icons</label> + <default>22</default> + </entry> + <entry key="display_file_tips" type="Bool" > + <label>Show file informations in tooltip</label> + <default>true</default> + </entry> + <entry key="display_previews_in_file_tips" type="Bool" > + <label>Show preview of the file in tooltip</label> + <default>false</default> + </entry> + <entry key="use_external_diff" type="Bool" > + <label>Use an external program for diff viewing/generating</label> + <default>false</default> + </entry> + <entry key="external_diff_display" type="String" > + <label>Use external program for diff viewing</label> + <default>kompare -on -</default> + </entry> + <entry key="external_display" type="String" > + <label>Use external program for viewing</label> + <default>default</default> + </entry> + <entry key="diff_ignore_content" type="Bool" > + <label>Diff ignores content type</label> + <default>false</default> + </entry> + <entry key="diff_ignore_spaces" type="Bool" > + <label>Diff ignores white space changes</label> + <default>false</default> + </entry> + <entry key="diff_ignore_all_white_spaces" type="Bool" > + <label>Diff ignores all white space</label> + <default>false</default> + </entry> + <entry key="max_log_messages" type="Int" > + <label>Maximum number of log messages</label> + <default>20</default> + </entry> + <entry key="colored_blame" type="Bool" > + <label>Display colored blame lines</label> + <default>true</default> + </entry> + <entry key="commit_splitter_height" type="IntList" > + <default>0,0</default> + </entry> + <entry key="commit_hide_new" type="Bool" > + <default>false</default> + </entry> + </group> + <group name="subversion" > + <entry key="display_overlays" type="Bool" > + <label>Display icon overlays</label> + <default>true</default> + </entry> + <entry key="info_recursive" type="Bool" > + <label>Get item informations recursively</label> + <default>false</default> + </entry> + <entry key="review_commit" type="Bool" > + <label>Review items before commit</label> + <default>true</default> + </entry> + <entry key="display_ignored_files" type="Bool" > + <label>Display ignored files</label> + <default>true</default> + </entry> + <entry key="display_unknown_files" type="Bool"> + <label>Display unknown files</label> + <default>true</default> + </entry> + <entry key="hide_unchanged_files" type="Bool"> + <label>Hide versioned unchanged files</label> + <default>false</default> + </entry> + <entry key="log_follows_nodes" type="Bool" > + <label>Log follows node changes</label> + <default>true</default> + </entry> + <entry key="log_always_list_changed_files" type="Bool" > + <label>Logs always reads list of changed files</label> + <default>true</default> + </entry> + <entry key="start_updates_check_on_open" type="Bool" > + <label>Start check for updates when open working copy</label> + <default>true</default> + </entry> + <entry key="log_cache_on_open" type="Bool"> + <label>Start caching latest logs on open or commit</label> + <default>true</default> + </entry> + <entry key="maximum_displayed_logs" type="UInt" > + <label>Maximum displayed logs when full log (0 for no limit)</label> + <default>0</default> + </entry> + <entry key="details_on_remote_listing" type="Bool" > + <label>Get detailed infos when making a remote listing</label> + <default>false</default> + </entry> + <entry key="properties_on_remote_items" type="Bool"> + <label>Get properties on selected item on networked protocols</label> + <default>false</default> + </entry> + <entry key="remote_special_properties" type="Bool"> + <label>Use properties like bugtraq:url on repository listings</label> + <default>true</default> + </entry> + <entry key="check_needslock" type="Bool"> + <label>Check for propertie svn:needs-lock on listings</label> + <default>false</default> + </entry> + <entry key="store_passwords" type="Bool" > + <label>Store passwords for remote connections</label> + <default>false</default> + </entry> + <entry key="passwords_in_wallet" type="Bool"> + <label>Store passwords in KDE Wallet instead subversion storage</label> + <default>true</default> + </entry> + <entry key="use_password_cache" type="Bool"> + <label>Use internal password cache</label> + <default>true</default> + </entry> + <entry key="network_on" type="Bool"> + <label>Is networking enabled</label> + <default>true</default> + </entry> + </group> + <group name="diffmerge_items"> + <entry key="external_merge_program" type="String" > + <label>Which program to use for external merges</label> + <default>kdiff3 %s1 %s2 %t</default> + </entry> + <entry key="conflict_resolver" type="String"> + <label>Wich program for resolving conflicts</label> + <default>kdiff3 %o %m %n -o %t</default> + </entry> + <entry name="extern_merge_default" type="Bool"> + <label>Prefer external merge program</label> + <default>false</default> + </entry> + </group> + <group name="display" > + <entry key="colored_state" type="Bool" > + <label>Display different then normal states colored</label> + <default>true</default> + </entry> + <entry key="color_need_update" type="Color" > + <default>101,224,76</default> + </entry> + <entry key="color_missed_item" type="Color" > + <default>#CC0000</default> + </entry> + <entry key="color_notversioned_item" type="Color" > + <default>#BBBBBB</default> + </entry> + <entry key="color_locked_item" type="Color" > + <default>#c50003</default> + </entry> + <entry key="color_need_lock" type="Color" > + <default>#ff8888</default> + </entry> + <entry key="color_item_deleted" type="Color" > + <default>#a3a3a3</default> + </entry> + <entry key="color_item_added" type="Color" > + <default>#85bae0</default> + </entry> + <entry key="color_changed_item" type="Color" > + <default>#de5e5e</default> + </entry> + <entry key="color_conflicted_item" type="Color" > + <default>255,0,0</default> + </entry> + </group> + <group name="blame_dlg"> + <entry key="locale_for_blame" type="String" > + <label>Locale for blame display</label> + <default></default> + </entry> + </group> + <group name="diff_display"> + <entry key="locale_for_diff" type="String" > + <default></default> + </entry> + </group> + <group name="revision_tree" > + <entry key="tree_direction" type="Int" > + <default>0</default> + <label>Direction of revision tree</label> + </entry> + <entry key="tree_add_color" type="Color" > + <default>#00FF00</default> + <label>Color for added items</label> + </entry> + <entry key="tree_delete_color" type="Color" > + <default>#FF0000</default> + <label>Color for deleted items</label> + </entry> + <entry key="tree_copy_color" type="Color" > + <default>#C0C0C0</default> + <label>Color for copied items</label> + </entry> + <entry key="tree_rename_color" type="Color" > + <default>#C0C0C0</default> + <label>Color for renamed items</label> + </entry> + <entry key="tree_modify_color" type="Color" > + <default>#a0a0a4</default> + <label>Color for modified items</label> + </entry> + <entry key="tree_detail_height" type="IntList" > + <default>0,0</default> + <label>Height of detail view in tree widget</label> + </entry> + <entry key="tree_diff_rec" type="Bool"> + <default>false</default> + <label>Diffs from Revisiontree are recursive</label> + </entry> + </group> + <group name="cmdline" > + <entry key="no_konqueror_contextmenu" type="Bool" > + <default>false</default> + <label>Should konqueror not display context menus for kdesvn?</label> + </entry> + <entry key="cmdline_show_logwindow" type="Bool" > + <default>true</default> + <label>Show a small logwindow after executing a command.</label> + </entry> + <entry key="cmdline_log_minline" type="UInt" > + <default>0</default> + <label>Log must contain at least lines to show</label> + </entry> + <entry key="kio_use_standard_logmsg" type="Bool" > + <default>false</default> + <label>KIO::svn operations uses a standard logmessage</label> + </entry> + <entry key="kio_standard_logmsg" type="String"> + <default>Revision made with kdesvn KIO.</default> + <label>The standard logmessage to use with KIO if not asking for it.</label> + </entry> + </group> + <group name="internals" > + <entry key="locale_is_casesensitive" type="Bool" > + <whatsthis>This value computes how casesensitive string ordering will made. +Never overwrite the default computed value unless you know what you're doing.</whatsthis> + <default code="true" >QString("a").localeAwareCompare("B")>0</default> + <label>Check if current locale is case sensitive or not</label> + </entry> + </group> +</kcfg> diff --git a/src/settings/kdesvnpartrc-use-external.upd b/src/settings/kdesvnpartrc-use-external.upd new file mode 100644 index 0000000..63a76c6 --- /dev/null +++ b/src/settings/kdesvnpartrc-use-external.upd @@ -0,0 +1,6 @@ +# kdesvnpartrc update +Id=0.14.0-1 +File=kdesvnpartrc +Group=general_items +Options=overwrite +Script=kdesvn-use-external-update.sh,sh diff --git a/src/settings/kdesvnsettings.kcfgc b/src/settings/kdesvnsettings.kcfgc new file mode 100644 index 0000000..db0aa07 --- /dev/null +++ b/src/settings/kdesvnsettings.kcfgc @@ -0,0 +1,6 @@ +# Code generation options for kconfig_compiler +File=kdesvn_part.kcfg +ClassName=Kdesvnsettings +Singleton=true +Mutators=true +# will create the necessary code for setting those variables diff --git a/src/settings/revisiontree_settings.ui b/src/settings/revisiontree_settings.ui new file mode 100644 index 0000000..2d9133e --- /dev/null +++ b/src/settings/revisiontree_settings.ui @@ -0,0 +1,247 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>RevisiontreeSettingsDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RevisionTreeSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>246</width> + <height>319</height> + </rect> + </property> + <property name="caption"> + <string>Revisiontree Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>kcfg_tree_direction</cstring> + </property> + <property name="title"> + <string>Direction of revision tree</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_LeftRight</cstring> + </property> + <property name="text"> + <string>Left to right</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_BottomTop</cstring> + </property> + <property name="text"> + <string>Bottom to top</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_RightLeft</cstring> + </property> + <property name="text"> + <string>Right to left</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_Topbottom</cstring> + </property> + <property name="text"> + <string>Top to bottom</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_AddColorLabel</cstring> + </property> + <property name="text"> + <string>Color for added items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>kcfg_tree_add_color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Color for deleted items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>kcfg_tree_delete_color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Color for copied items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>kcfg_tree_copy_color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Color for renamed items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>kcfg_tree_rename_color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Color for modified items:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>kcfg_tree_modify_color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<tabstops> + <tabstop>m_LeftRight</tabstop> + <tabstop>m_RightLeft</tabstop> + <tabstop>m_Topbottom</tabstop> + <tabstop>m_BottomTop</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/src/settings/revisiontreesettingsdlg_impl.cpp b/src/settings/revisiontreesettingsdlg_impl.cpp new file mode 100644 index 0000000..0cad80f --- /dev/null +++ b/src/settings/revisiontreesettingsdlg_impl.cpp @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "src/settings/revisiontreesettingsdlg_impl.h" + +RevisiontreeSettingsDlg_impl::RevisiontreeSettingsDlg_impl(QWidget *parent, const char *name) + :RevisiontreeSettingsDlg(parent, name) +{ +} + +RevisiontreeSettingsDlg_impl::~RevisiontreeSettingsDlg_impl() +{ +} + +#include "revisiontreesettingsdlg_impl.moc" diff --git a/src/settings/revisiontreesettingsdlg_impl.h b/src/settings/revisiontreesettingsdlg_impl.h new file mode 100644 index 0000000..cc17b72 --- /dev/null +++ b/src/settings/revisiontreesettingsdlg_impl.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REVISIONTREESETTINGSDLG_IMPL_H +#define REVISIONTREESETTINGSDLG_IMPL_H + +#include "src/settings/revisiontree_settings.h" + +class RevisiontreeSettingsDlg_impl: public RevisiontreeSettingsDlg +{ + Q_OBJECT +public: + RevisiontreeSettingsDlg_impl(QWidget *parent = 0, const char *name = 0); + virtual ~RevisiontreeSettingsDlg_impl(); +}; + +#endif diff --git a/src/settings/subversion_settings.ui b/src/settings/subversion_settings.ui new file mode 100644 index 0000000..9d86625 --- /dev/null +++ b/src/settings/subversion_settings.ui @@ -0,0 +1,249 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>SubversionSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>SubversionSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>339</width> + <height>410</height> + </rect> + </property> + <property name="caption"> + <string>Subversion Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_start_updates_check_on_open</cstring> + </property> + <property name="text"> + <string>Start check for updates when open a working copy</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Select if kdesvn should check for updates when open a working copy</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_log_cache_on_open</cstring> + </property> + <property name="text"> + <string>Start fill log cache on open</string> + </property> + <property name="toolTip" stdset="0"> + <string>Start refresh the logcache for repository when networking enabled</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_check_needslock</cstring> + </property> + <property name="text"> + <string>Check if items has "svn:needs-lock" property set</string> + </property> + <property name="toolTip" stdset="0"> + <string>When listing on working copies kdesvn may check for this property</string> + </property> + <property name="whatsThis" stdset="0"> + <string>When listing on working copies kdesvn may check for <tt>svn:needs-lock</tt> property.<br>But due this listings/updating on folders containing lot of items may get slow. So you should only switch on if you have repositories containing lot of such entries.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_details_on_remote_listing</cstring> + </property> + <property name="text"> + <string>Get file details while remote listing</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Whether getting details about items when making listing on repositories or not</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p align="left">When checked, kdesvn get more detailed info about file items when making a listing to remote repositories. So you may see remote locks in overview. +</p> +<p align="left"><i>Be careful: This may let listings REAL slow!</i></p></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_info_recursive</cstring> + </property> + <property name="text"> + <string>Gain item info recursive</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_properties_on_remote_items</cstring> + </property> + <property name="text"> + <string>Always get properties on networked repositories</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Should kdesvn retrieves properties on selected item in repositories</string> + </property> + <property name="whatsThis" stdset="0"> + <string>When browsing kdesvn may try displaying properties below itemlist from a selected item. +On networked repositories (eg., not opened via file:// protocol) this may get real slow. So if you have slow network connections or when browsing hangs often you should deactivate it.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_store_passwords</cstring> + </property> + <property name="text"> + <string>Store passwords for remote connections</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Should subversion store passwords in default</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Storing passwords is often a security problem. Kdesvn itself doesn't store any passwords, but the subversion itself inside the configuration area of subversion. If this area is readable from others you should not set it, but you may select for single non critical accounts inside the authentication dialog.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_passwords_in_wallet</cstring> + </property> + <property name="text"> + <string>Store passwords into KDE Wallet</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>When saving passwords, do it into KDE wallet instead of subversions storage?</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p>Tells if your passwords set in kdesvn should stored into kde wallet instead of simple cleartext storage of subversion.</p> +<p>This would be a little bit more secure 'cause KDE wallet is (mostly) encrypted with a password. On other hand you must re-enter your passwords with other subversion clients not accessing KDE wallet (eg. svn commandline itself, rapidsvn and so on).</p> +<p>If you're HOME storage eg. subversions configfolder is on a network drive you should hard think about not storing passwords in a plain text file like subversion does but put it into an encrypted storage like kde wallet or don't save passwords.</p></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_use_password_cache</cstring> + </property> + <property name="text"> + <string>Use internal password cache</string> + </property> + <property name="toolTip" stdset="0"> + <string>Use an internal password cache</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_log_follows_nodes</cstring> + </property> + <property name="text"> + <string>Log follows node changes</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_log_always_list_changed_files</cstring> + </property> + <property name="text"> + <string>Logs always reads list of changed files</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Read detailed change lists</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Reading lists of changed files may sometimes a little bit slow down things. But if this feature is switched off, kdesvn may fail generating differences between nodechanges from within the logviewer.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_review_commit</cstring> + </property> + <property name="text"> + <string>Review items before commit</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>List items next commit will send or not</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_commit_hide_new</cstring> + </property> + <property name="text"> + <string>Hide new items in commit box</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Should unversioned items displayed in commit dialog or not.</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>kcfg_maximum_displayed_logs</cstring> + </property> + <property name="label"> + <string>Maximum displayed logs when full log (0 for no limit)</string> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/src/settings/subversionsettings_impl.cpp b/src/settings/subversionsettings_impl.cpp new file mode 100644 index 0000000..aa0e96a --- /dev/null +++ b/src/settings/subversionsettings_impl.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "subversionsettings_impl.h" + +SubversionSettings_impl::SubversionSettings_impl(QWidget* parent, const char* name, WFlags fl) +: SubversionSettings(parent,name,fl) +{ +} + +SubversionSettings_impl::~SubversionSettings_impl() +{ +} + +/*$SPECIALIZATION$*/ + + +#include "subversionsettings_impl.moc" + diff --git a/src/settings/subversionsettings_impl.h b/src/settings/subversionsettings_impl.h new file mode 100644 index 0000000..e2c42ec --- /dev/null +++ b/src/settings/subversionsettings_impl.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef SUBVERSIONSETTINGS_IMPL_H +#define SUBVERSIONSETTINGS_IMPL_H + +#include "src/settings/subversion_settings.h" + +class SubversionSettings_impl : public SubversionSettings +{ + Q_OBJECT + +public: + SubversionSettings_impl(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~SubversionSettings_impl(); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + +protected: + /*$PROTECTED_FUNCTIONS$*/ + +protected slots: + /*$PROTECTED_SLOTS$*/ + +}; + +#endif + diff --git a/src/svnfrontend/CMakeLists.txt b/src/svnfrontend/CMakeLists.txt new file mode 100644 index 0000000..79cac7f --- /dev/null +++ b/src/svnfrontend/CMakeLists.txt @@ -0,0 +1,86 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/svnfrontend/fronthelpers ${CMAKE_BINARY_DIR}/src/svnqt) + +SET(svnfrontendsrc + ccontextlistener.cpp + commandexec.cpp + copymoveview_impl.cpp + createrepo_impl.cpp + dummydisplay.cpp + dumprepo_impl.cpp + editproperty_impl.cpp + filelistviewitem.cpp + fronthelpers/checkoutinfo_impl.cpp + fronthelpers/checkoutinfo_impl.h + fronthelpers/rangeinput_impl.cpp + fronthelpers/rangeinput_impl.h + fronthelpers/revisionbuttonimpl.cpp + fronthelpers/revisionbuttonimpl.h + fronthelpers/cursorstack.h + fronthelpers/widgetblockstack.cpp + fronthelpers/widgetblockstack.h + fronthelpers/propertylist.cpp + fronthelpers/propertylist.h + fronthelpers/propertyitem.cpp + fronthelpers/propertyitem.h + graphtree/drawparams.cpp + graphtree/drawparams.h + graphtree/elogentry.cpp + graphtree/elogentry.h + graphtree/graphtreelabel.cpp + graphtree/graphtreelabel.h + graphtree/pannerview.cpp + graphtree/pannerview.h + graphtree/revgraphview.cpp + graphtree/revgraphview.h + graphtree/revisiontree.cpp + graphtree/revisiontree.h + graphtree/revtreewidget.cpp + graphtree/revtreewidget.h + hotcopydlg_impl.cpp + importdir_logmsg.cpp + itemdisplay.cpp + kdesvnfilelist.cpp + keystatus.cpp + loaddmpdlg_impl.cpp + mergedlg_impl.cpp + modifiedthread.cpp + opencontextmenu.cpp + propertiesdlg.cpp + stopdlg.cpp + svnactions.cpp + svnfiletip.cpp + svnitem.cpp + svnlogdlgimp.cpp + tcontextlistener.cpp + blamedisplay_impl.cpp + threadcontextlistenerdata.cpp + fillcachethread.cpp + fillcachethread.h + ) + +SET(svnfrontendui + copymoveview.ui + createrepo_dlg.ui + dumprepo_dlg.ui + editpropsdlg.ui + fronthelpers/checkoutinfo.ui + fronthelpers/rangeinput.ui + fronthelpers/revisionbutton.ui + hotcopydlg.ui + loaddmpdlg.ui + merge_dlg.ui + blamedisplay.ui + svnlogdlg.ui + ) + +FILE(GLOB hdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h") + +KDE3_AUTOMOC(${svnfrontendsrc}) +KDE3_ADD_UI_FILES(frontend_ui_sources ${svnfrontendui}) + +ADD_LIBRARY(svnfrontend STATIC ${svnfrontendsrc} ${frontend_ui_sources} ${hdr}) +SET_TARGET_PROPERTIES(svnfrontend + PROPERTIES + COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) + +ADD_DEPENDENCIES(svnfrontend ksvnwidgets) diff --git a/src/svnfrontend/blamedisplay.ui b/src/svnfrontend/blamedisplay.ui new file mode 100644 index 0000000..3f5a48c --- /dev/null +++ b/src/svnfrontend/blamedisplay.ui @@ -0,0 +1,108 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>BlameDisplay</class> +<widget class="QWidget"> + <property name="name"> + <cstring>BlameDisplay</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>341</width> + <height>243</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListView"> + <column> + <property name="text"> + <string>Line</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Revision</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Date</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Author</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Content</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_BlameList</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_BlameList</sender> + <signal>contextMenu(KListView*,QListViewItem*,const QPoint&)</signal> + <receiver>BlameDisplay</receiver> + <slot>slotContextMenuRequested(KListView*,QListViewItem*,const QPoint&)</slot> + </connection> + <connection> + <sender>m_BlameList</sender> + <signal>doubleClicked(QListViewItem*)</signal> + <receiver>BlameDisplay</receiver> + <slot>slotItemDoubleClicked(QListViewItem*)</slot> + </connection> +</connections> +<slots> + <slot access="protected">slotContextMenuRequested(KListView*,QListViewItem*, const QPoint&)</slot> + <slot access="protected">slotItemDoubleClicked(QListViewItem*)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klistview.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/blamedisplay_impl.cpp b/src/svnfrontend/blamedisplay_impl.cpp new file mode 100644 index 0000000..36381e4 --- /dev/null +++ b/src/svnfrontend/blamedisplay_impl.cpp @@ -0,0 +1,490 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "blamedisplay_impl.h" +#include "simple_logcb.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/log_entry.hpp" +#include "fronthelpers/cursorstack.h" +#include "fronthelpers/widgetblockstack.h" +#include "src/ksvnwidgets/encodingselector_impl.h" + +#include <klistview.h> +#include <kglobalsettings.h> +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kinputdialog.h> +#include <kmessagebox.h> +#include <kdialogbase.h> +#include <kapp.h> +#include <ktextbrowser.h> +#include <klistviewsearchline.h> + +#include <qpixmap.h> +#include <qpainter.h> +#include <qheader.h> +#include <qmap.h> +#include <qpopupmenu.h> +#include <qvbox.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qlayout.h> +#include <qtextcodec.h> + +#define COL_LINENR 0 +#define COL_REV 1 +#define COL_DATE 2 +#define COL_AUT 3 +#define COL_LINE 4 + +class LocalizedAnnotatedLine:public svn::AnnotateLine +{ +public: + LocalizedAnnotatedLine(const svn::AnnotateLine&al) + :svn::AnnotateLine(al) + { + localeChanged(); + } + + void localeChanged() + { + if (!codec_searched) { + cc = QTextCodec::codecForName(Kdesvnsettings::locale_for_blame()); + codec_searched = true; + } + if (cc) { + m_tLine=cc->toUnicode(line().data(),line().size()); + m_tAuthor=cc->toUnicode(author().data(),author().size()); + } else { + m_tLine=QString::FROMUTF8(line().data(),line().size()); + m_tAuthor=QString::FROMUTF8(author().data(),author().size()); + } + } + + const QString& tAuthor()const{return m_tAuthor;} + const QString& tLine()const{return m_tLine;} + + static void reset_codec(){codec_searched = false; cc=0;} + +protected: + QString m_tAuthor,m_tLine; + + static bool codec_searched; + static QTextCodec * cc; +}; + +QTextCodec* LocalizedAnnotatedLine::cc = 0; +bool LocalizedAnnotatedLine::codec_searched = false; + +class BlameDisplayItem:public KListViewItem +{ +public: + BlameDisplayItem(KListView*,const svn::AnnotateLine&,bool,BlameDisplay_impl*); + BlameDisplayItem(KListView*,BlameDisplayItem*,const svn::AnnotateLine&,bool,BlameDisplay_impl*); + virtual ~BlameDisplayItem(){} + virtual int compare(QListViewItem *i, int col, bool ascending)const; + virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + virtual int rtti()const{return 1000;} + + virtual int width( const QFontMetrics & fm, const QListView * lv, int c ) const; + + apr_int64_t lineNumber(){return m_Content.lineNumber();} + svn_revnum_t rev(){return m_Content.revision();} + + void localeChanged() + { + m_Content.localeChanged(); + if (m_disp){ + setText(COL_AUT,m_Content.tAuthor()); + } + QString _line = m_Content.tLine(); + _line.replace("\t"," "); + setText(COL_LINE,QString("%1").arg(_line)); + } + +protected: + LocalizedAnnotatedLine m_Content; + + bool m_disp; + + void display(); + BlameDisplay_impl*cb; +}; + +BlameDisplayItem::BlameDisplayItem(KListView*lv,const svn::AnnotateLine&al,bool disp,BlameDisplay_impl*_c) + : KListViewItem(lv),m_Content(al),m_disp(disp),cb(_c) +{ + display(); +} + +BlameDisplayItem::BlameDisplayItem(KListView*lv,BlameDisplayItem*it,const svn::AnnotateLine&al,bool disp,BlameDisplay_impl*_c) + : KListViewItem(lv,it),m_Content(al),m_disp(disp),cb(_c) +{ + display(); +} + +#define BORDER 4 + +int BlameDisplayItem::width (const QFontMetrics & fm, const QListView * lv, int c ) const +{ + if (c == COL_LINE) { + return KListViewItem::width(QFontMetrics(KGlobalSettings::fixedFont()),lv,c)+2*BORDER; + } + return KListViewItem::width(fm,lv,c)+2*BORDER; +} + +void BlameDisplayItem::display() +{ + if (m_disp){ + setText(COL_REV,QString("%1").arg(m_Content.revision())); + setText(COL_AUT,m_Content.tAuthor()); + if (m_Content.date().isValid()) { + setText(COL_DATE,KGlobal::locale()->formatDateTime(m_Content.date())); + } + } + + setText(COL_LINENR,QString("%1").arg(m_Content.lineNumber()+1)); + QString _line = m_Content.tLine(); + _line.replace("\t"," "); + setText(COL_LINE,QString("%1").arg(_line)); +} + +int BlameDisplayItem::compare(QListViewItem *item, int col, bool ascending)const +{ + Q_UNUSED(ascending); + BlameDisplayItem* k = static_cast<BlameDisplayItem*>(item); + if (col == COL_REV) { + return k->m_Content.revision()-m_Content.revision(); + } + if (col == COL_AUT) { + if (Kdesvnsettings::locale_is_casesensitive()) { + return m_Content.tAuthor().localeAwareCompare(k->m_Content.author()); + } + return m_Content.tAuthor().compare(k->m_Content.author()); + } + return k->m_Content.lineNumber()-m_Content.lineNumber(); +} + +void BlameDisplayItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + if (alignment & (AlignTop || AlignBottom) == 0) + alignment |= AlignVCenter; + + /* don't copy string */ + const QString & str = text(column);; + if (column == COL_LINE) { + p->setFont(KGlobalSettings::fixedFont()); + } + + QColorGroup _cg = cg; + QColor _bgColor; + if (column==COL_LINENR || isSelected()) { + _bgColor = KGlobalSettings::highlightColor(); + p->setPen(KGlobalSettings::highlightedTextColor()); + } else { + if (Kdesvnsettings::self()->colored_blame()) { + _bgColor = cb->rev2color(m_Content.revision()); + } else { + _bgColor = listView()->viewport()->colorGroup().base(); + } + } + + p->fillRect(0, 0, width, height(), _bgColor); + if (column==COL_AUT) { + p->drawLine(width-1,0,width-1,height()); + } + + if (str.isEmpty()) + return; + p->drawText(BORDER, 0, width - 2*BORDER, height(), alignment, str); +} + +class BlameDisplayData +{ + public: + BlameDisplayData() + { + max=-1; + min=INT_MAX-1; + rev_count=0; + up=false; + m_cb=0;m_File=""; + m_dlg = 0; + } + ~BlameDisplayData(){} + svn_revnum_t max,min; + QMap<svn_revnum_t,QColor> m_shadingMap; + QMap<svn_revnum_t,svn::LogEntry> m_logCache; + + QColor m_lastCalcColor; + unsigned int rev_count; + bool up; + SimpleLogCb*m_cb; + QString m_File; + KDialogBase*m_dlg; + + QString reposRoot; +}; + +BlameDisplay_impl::BlameDisplay_impl(QWidget*parent,const char*name) + : BlameDisplay(parent,name) +{ + m_Data = new BlameDisplayData(); + connect(m_BlameList,SIGNAL(selectionChanged()),this,SLOT(slotSelectionChanged())); +} + +BlameDisplay_impl::BlameDisplay_impl(const QString&what,const svn::AnnotatedFile&blame,QWidget*parent,const char*name) + : BlameDisplay(parent,name) +{ + m_Data = new BlameDisplayData(); + connect(m_BlameList,SIGNAL(selectionChanged()),this,SLOT(slotSelectionChanged())); + setContent(what,blame); +} + +void BlameDisplay_impl::setCb(SimpleLogCb*_cb) +{ + m_Data->m_cb = _cb; +} + +void BlameDisplay_impl::setContent(const QString&what,const svn::AnnotatedFile&blame) +{ + m_Data->m_File = what; + m_SearchWidget = new KListViewSearchLineWidget(m_BlameList,this); + EncodingSelector_impl*m_Ls = new EncodingSelector_impl(Kdesvnsettings::locale_for_blame(),this); + connect(m_Ls,SIGNAL(TextCodecChanged(const QString&)), + this,SLOT(slotTextCodecChanged(const QString&))); + + BlameDisplayLayout->remove(m_BlameList); + BlameDisplayLayout->addWidget(m_Ls); + BlameDisplayLayout->addWidget(m_SearchWidget); + BlameDisplayLayout->addWidget(m_BlameList); + + m_BlameList->setColumnAlignment(COL_REV,Qt::AlignRight); + m_BlameList->setColumnAlignment(COL_LINENR,Qt::AlignRight); + + m_BlameList->clear(); + if (m_Data->m_dlg) { + m_Data->m_dlg->enableButton(KDialogBase::User2,false); + } + svn::AnnotatedFile::const_iterator bit; + m_BlameList->setSorting(COL_LINENR,false); + m_Data->max = -1; + svn_revnum_t lastRev(-1); + for (bit=blame.begin();bit!=blame.end();++bit) { + bool disp = (*bit).revision()!=lastRev || bit==blame.begin() ; + + if ((*bit).revision()>m_Data->max) {m_Data->max=(*bit).revision();++(m_Data->rev_count);} + if ((*bit).revision()<m_Data->min) m_Data->min=(*bit).revision(); + new BlameDisplayItem(m_BlameList,(*bit),disp,this); + if (disp) { + lastRev = (*bit).revision(); + } + if (m_Data->m_shadingMap.find((*bit).revision())==m_Data->m_shadingMap.end()) { + m_Data->m_shadingMap[(*bit).revision()]=QColor(); + } + } + if (Kdesvnsettings::self()->colored_blame()) { + QColor a(160,160,160); + int offset = 10; + int r=0; int g=0;int b=0; + uint colinc=0; + + for (svn_revnum_t i = m_Data->min; i<= m_Data->max;++i) { + if (m_Data->m_shadingMap.find(i)==m_Data->m_shadingMap.end()) { + continue; + } + a.setRgb(a.red()+offset,a.green()+offset,a.blue()+offset); + m_Data->m_shadingMap[i]=a; + if ( a.red()>245||a.green()>245||a.blue()>245 ) { + if (colinc==0) { + ++colinc; + } else if (r>=50||g>=50||b>=50) { + if (++colinc>6) { + colinc = 0; + r=g=b=0; + } else { + r=g=b=-10; + } + } + if (colinc & 0x1) { + r+=10; + } + if (colinc & 0x2) { + g+=10; + } + if (colinc & 0x4) { + b+=10; + } + a.setRgb(160+r,160+g,160+b); + } + } + } +} + +const QColor BlameDisplay_impl::rev2color(svn_revnum_t r )const +{ + if (m_Data->m_shadingMap.find(r)!=m_Data->m_shadingMap.end() && m_Data->m_shadingMap[r].isValid()) + { + return m_Data->m_shadingMap[r]; + } else { + return m_BlameList->viewport()->colorGroup().base(); + } +} + +BlameDisplay_impl::~BlameDisplay_impl() +{ + delete m_Data; +} + +void BlameDisplay_impl::slotGoLine() +{ + bool ok = true; + int line = KInputDialog::getInteger(i18n("Show line"),i18n("Show line number"), + 1,1,m_BlameList->childCount(),1,&ok,this); + if (!ok) { + return; + } + QListViewItem*item = m_BlameList->firstChild(); + --line; + while (item) { + if (item->rtti()==1000) { + BlameDisplayItem*bit = static_cast<BlameDisplayItem*>(item); + if (bit->lineNumber()==line) { + m_BlameList->ensureItemVisible(bit); + m_BlameList->setSelected(bit,true); + return; + } + } + item = item->nextSibling(); + } +} + +void BlameDisplay_impl::slotContextMenuRequested(KListView*,QListViewItem*item, const QPoint&pos) +{ + if (item==0||item->rtti()!=1000) return; + BlameDisplayItem*bit = static_cast<BlameDisplayItem*>(item); + QPopupMenu popup; + popup.insertItem(i18n("Log message for revision"),101); + int r = popup.exec(pos); + + switch (r) + { + case 101: + showCommit(bit); + break; + default: + break; + } +} + +void BlameDisplay_impl::showCommit(BlameDisplayItem*bit) +{ + if (!bit) return; + WidgetBlockStack a(m_BlameList); + QString text; + if (m_Data->m_logCache.find(bit->rev())!=m_Data->m_logCache.end()) { + text = m_Data->m_logCache[bit->rev()].message; + } else { + CursorStack a(Qt::BusyCursor); + svn::LogEntry t; + if (m_Data->m_cb && m_Data->m_cb->getSingleLog(t,bit->rev(),m_Data->m_File,m_Data->max,m_Data->reposRoot)) { + m_Data->m_logCache[bit->rev()] = t; + text = m_Data->m_logCache[bit->rev()].message; + } + } + KDialogBase* dlg = new KDialogBase( + KApplication::activeModalWidget(), + "simplelog",true,QString(i18n("Logmessage for revision %1").arg(bit->rev())), + KDialogBase::Close); + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + KTextBrowser*ptr = new KTextBrowser(Dialog1Layout); + ptr->setFont(KGlobalSettings::fixedFont()); + ptr->setWordWrap(QTextEdit::NoWrap); + ptr->setText(text); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"simplelog_display")); + dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"simplelog_display",false); +} + +void BlameDisplay_impl::slotShowCurrentCommit() +{ + QListViewItem*item = m_BlameList->selectedItem(); + if (item==0||item->rtti()!=1000) return; + BlameDisplayItem*bit = static_cast<BlameDisplayItem*>(item); + showCommit(bit); +} + +void BlameDisplay_impl::slotSelectionChanged() +{ + if (!m_Data->m_dlg) return; + QListViewItem*item = m_BlameList->selectedItem(); + if (item==0||item->rtti()!=1000) { + m_Data->m_dlg->enableButton(KDialogBase::User2,false); + } else { + m_Data->m_dlg->enableButton(KDialogBase::User2,true); + } +} + +void BlameDisplay_impl::displayBlame(SimpleLogCb*_cb,const QString&item,const svn::AnnotatedFile&blame,QWidget*,const char*name) +{ + int buttons = KDialogBase::Close|KDialogBase::User1|KDialogBase::User2; + KDialogBase * dlg = new KDialogBase( + KApplication::activeModalWidget(), + name,true,QString(i18n("Blame %1")).arg(item),buttons,KDialogBase::Close,false, + KGuiItem(i18n("Goto line")),KGuiItem(i18n("Log message for revision"),"kdesvnlog")); + + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + BlameDisplay_impl*ptr = new BlameDisplay_impl(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"blame_dlg")); + ptr->setContent(item,blame); + ptr->setCb(_cb); + ptr->m_Data->m_dlg = dlg; + dlg->enableButton(KDialogBase::User2,false); + connect(dlg,SIGNAL(user1Clicked()),ptr,SLOT(slotGoLine())); + connect(dlg,SIGNAL(user2Clicked()),ptr,SLOT(slotShowCurrentCommit())); + Dialog1Layout->adjustSize(); + dlg->exec(); + + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"blame_dlg",false); +} + +void BlameDisplay_impl::slotItemDoubleClicked(QListViewItem*item) +{ + if (item==0||item->rtti()!=1000) return; + BlameDisplayItem*bit = static_cast<BlameDisplayItem*>(item); + showCommit(bit); +} + +void BlameDisplay_impl::slotTextCodecChanged(const QString&what) +{ + if (Kdesvnsettings::locale_for_blame()!=what) { + Kdesvnsettings::setLocale_for_blame(what); + Kdesvnsettings::self()->writeConfig(); + LocalizedAnnotatedLine::reset_codec(); + QListViewItemIterator it(m_BlameList); + while ( it.current() ) { + BlameDisplayItem*_it = static_cast<BlameDisplayItem*>(it.current()); + _it->localeChanged(); + ++it; + } + } +} + +#include "blamedisplay_impl.moc" diff --git a/src/svnfrontend/blamedisplay_impl.h b/src/svnfrontend/blamedisplay_impl.h new file mode 100644 index 0000000..013e05a --- /dev/null +++ b/src/svnfrontend/blamedisplay_impl.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef BLAMEDISPLAY_IMPL_H +#define BLAMEDISPLAY_IMPL_H + +#include "blamedisplay.h" +#include "src/svnqt/client.hpp" + +class BlameDisplayData; +class SimpleLogCb; +class BlameDisplayItem; +class KListViewSearchLineWidget; + +class BlameDisplay_impl:public BlameDisplay +{ + Q_OBJECT +public: + BlameDisplay_impl(const QString&,const svn::AnnotatedFile&,QWidget*parent=0,const char*name=0); + BlameDisplay_impl(QWidget*parent=0,const char*name=0); + virtual ~BlameDisplay_impl(); + + virtual void setContent(const QString&,const svn::AnnotatedFile&); + virtual void setCb(SimpleLogCb*); + + const QColor rev2color(svn_revnum_t)const; + + static void displayBlame(SimpleLogCb*,const QString&,const svn::AnnotatedFile&,QWidget*parent=0,const char*name=0); + +public slots: + virtual void slotGoLine(); + virtual void slotShowCurrentCommit(); + +protected slots: + virtual void slotContextMenuRequested(KListView*,QListViewItem*, const QPoint&); + virtual void slotSelectionChanged(); + virtual void slotTextCodecChanged(const QString&); + +protected: + virtual void showCommit(BlameDisplayItem*); + KListViewSearchLineWidget* m_SearchWidget; + +private: + BlameDisplayData*m_Data; +protected slots: + virtual void slotItemDoubleClicked(QListViewItem*); +}; + +#endif diff --git a/src/svnfrontend/cacheentry.h b/src/svnfrontend/cacheentry.h new file mode 100644 index 0000000..2ab422b --- /dev/null +++ b/src/svnfrontend/cacheentry.h @@ -0,0 +1,581 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef HELPERSCACHEENTRY_H +#define HELPERSCACHEENTRY_H + +#include "src/svnqt/svnqttypes.hpp" +#include "src/svnqt/shared_pointer.hpp" +#include "src/svnqt/status.hpp" + +// std::map 'cause QMap isn't usable +#include <map> +#include <algorithm> +#include <qstring.h> +#include <qstringlist.h> + +namespace helpers { + +/** + Class for fast search of path based items. + + @author Rajko Albrecht <ral@alwins-world.de> +*/ +template<class C> class cacheEntry { +public: + typedef cacheEntry<C> cache_type; + typedef typename std::map<QString,cache_type> cache_map_type; + typedef typename cache_map_type::const_iterator citer; + typedef typename cache_map_type::iterator iter; + +protected: + QString m_key; + bool m_isValid; + C m_content; + cache_map_type m_subMap; + +public: + cacheEntry(); + cacheEntry(const QString&key); + cacheEntry(const cacheEntry<C>&other); + + virtual ~cacheEntry(){}; + + virtual bool find(QStringList&,QLIST<C>&)const; + //! Checks if cache contains a specific item + /*! + * the keylist will manipulated - so copy-operations aren't needed. + * \param what Stringlist containing the components to search for + * \return true if found (may or may not valid!) otherwise false + */ + virtual bool find(QStringList&what)const; + //! Checks if cache contains a specific valid item + /*! + * if yes, the content will stored in st + * \param what the keylist to search for + * \param st target status to store content if found + * \return true if found + */ + virtual bool findSingleValid(QStringList&what,C&st)const; + //! Checks if cache contains a specific valid item + /*! + * in difference to virtual bool find(QStringList&,svn::StatusEntries&)const no copy operations + * are made inside so it works much faster for simple find. + * \param what the keylist to search for + * \param check_valid_subs if true, return true if a subitem is valid even the item isn't valid + * \return true if found + */ + virtual bool findSingleValid(QStringList&what,bool check_valid_subs)const; + template<class T> void listsubs_if(QStringList&_what,T&oper)const; + + virtual void appendValidSub(QLIST<C>&)const; + virtual bool isValid()const + { + return m_isValid; + } + virtual const C&content()const + { + return m_content; + } + virtual bool deleteKey(QStringList&,bool exact); + virtual void insertKey(QStringList&,const C&); + virtual void setValidContent(const QString&key,const C&st) + { + kdDebug()<<"Insert for "<<key<<endl; + m_key = key; + m_isValid=true; + m_content=st; + } + virtual bool hasValidSubs()const; + virtual void markInvalid() { + m_content=C(); + m_isValid=false; + } + const QString&key()const { + return m_key; + } + + cacheEntry<C>& operator=(const cacheEntry<C>&other); +#if 0 + void dump_tree(int level=0)const + { + QString pre; + pre.fill('-',level); + std::map<QString,cacheEntry>::const_iterator it; + for (it=m_subMap.begin();it!=m_subMap.end();++it) { + std::cout<<pre.latin1()<<it->first.latin1() << " (" << it->second.m_key.latin1() << ")"<<std::endl; + it->second.dump_tree(level+1); + } + } +#endif +}; + +typedef cacheEntry<svn::StatusPtr> statusEntry; + +template<class C> inline cacheEntry<C>::cacheEntry() + : m_key(""),m_isValid(false),m_content() +{ +} + +template<class C> inline cacheEntry<C>::cacheEntry(const QString&key) + : m_key(key),m_isValid(false),m_content() +{ +} + +template<class C> inline cacheEntry<C>::cacheEntry(const cacheEntry<C>&other) + : m_key(other.m_key),m_isValid(other.m_isValid), + m_content(other.m_content),m_subMap(other.m_subMap) +{ +} + +template<class C> inline cacheEntry<C>& cacheEntry<C>::operator=(const cacheEntry<C>&other) +{ + m_key=other.m_key; + m_isValid = other.m_isValid; + m_content = other.m_content; + m_subMap = other.m_subMap; + return *this; +} + +template<class C> inline bool cacheEntry<C>::find(QStringList&what,QLIST<C>&t)const +{ + if (what.count()==0) { + return false; + } + citer it; + it = m_subMap.find(what[0]); + if (it==m_subMap.end()) { + // kdDebug()<<what[0]<< " not found in tree"<<endl; + return false; + } + // kdDebug()<<what[0]<< " found in tree"<<endl; + if (what.count()==1) { + // kdDebug()<<"Seems last item in stage "<< m_key << " - " << what[0] << endl; +// if (it->second.m_key == what[0]) { + /* the item itself */ + if (it->second.isValid()) { + t.append(it->second.content()); + } + /* and now check valid subitems */ + // kdDebug()<<"Appending valid subs"<<endl; + it->second.appendValidSub(t); + // kdDebug()<<"Appended valid subs"<<endl; + return true; +// } + return false; + } + what.erase(what.begin()); + // kdDebug()<<"Searching "<<what<<" in next stage"<<endl; + return it->second.find(what,t); +} + +template<class C> inline bool cacheEntry<C>::find(QStringList&what)const +{ + if (what.count()==0) { + return false; + } + citer it = m_subMap.find(what[0]); + if (it==m_subMap.end()) { + return false; + } + if (what.count()==1) { + return true; + } + what.erase(what.begin()); + return it->second.find(what); +} + +template<class C> inline bool cacheEntry<C>::findSingleValid(QStringList&what,C&t)const +{ + if (what.count()==0) { + return false; + } + //kdDebug()<<"cacheEntry::findSingleValid(QStringList&what,C&t)"<< what << endl; + citer it; + it = m_subMap.find(what[0]); + if (it==m_subMap.end()) { + //kdDebug()<<"Not found here..."<<endl; + return false; + } + if (what.count()==1) { + //kdDebug()<<"Found here and set content. "<<it->second.isValid()<<endl; + t=it->second.content(); + return it->second.isValid(); + } + what.erase(what.begin()); + //kdDebug()<<"Search next stage down..."<<endl; + return it->second.findSingleValid(what,t); +} + +template<class C> inline bool cacheEntry<C>::findSingleValid(QStringList&what,bool check_valid_subs)const +{ + if (what.count()==0) { + return false; + } + // kdDebug()<<"cacheEntry::findSingleValid(QStringList&what,svn::Status&t)"<< what << endl; + citer it = m_subMap.find(what[0]); + if (it==m_subMap.end()) { + return false; + } + if (what.count()==1) { + return it->second.isValid()||(check_valid_subs&&it->second.hasValidSubs()); + } + what.erase(what.begin()); + return it->second.findSingleValid(what,check_valid_subs); +} + +template<class C> inline void cacheEntry<C>::appendValidSub(QLIST<C>&t)const +{ + citer it; + for (it=m_subMap.begin();it!=m_subMap.end();++it) { + if (it->second.isValid()) { + // kdDebug()<<"Appending single sub"<<endl; + t.append(it->second.content()); + } else { + // kdDebug()<<it->second.key()<<" isnt valid"<<endl; + } + it->second.appendValidSub(t); + } +} + +template<class C> inline bool cacheEntry<C>::deleteKey(QStringList&what,bool exact) +{ + if (what.count()==0) { + return true; + } + iter it=m_subMap.find(what[0]); + if (it==m_subMap.end()) { + return true; + } + bool caller_must_check = false; + /* first stage - we are the one holding the right key */ + if (what.count()==1){ + if (!exact || !it->second.hasValidSubs()) { + m_subMap.erase(it); + caller_must_check = true; + } else { + it->second.markInvalid(); + } + } else { + /* otherwise go trough tree */ + what.erase(what.begin()); + bool b = it->second.deleteKey(what,exact); + if (b && !it->second.hasValidSubs()) { + m_subMap.erase(it); + caller_must_check = true; + } + } + return caller_must_check; +} + +template<class C> inline bool cacheEntry<C>::hasValidSubs()const +{ + citer it; + for (it=m_subMap.begin();it!=m_subMap.end();++it) { + if (it->second.isValid()||it->second.hasValidSubs()) { + return true; + } + } + return false; +} + +template<class C> inline void cacheEntry<C>::insertKey(QStringList&what,const C&st) +{ + if (what.count()==0) { + return; + } + //kdDebug()<<"inserting "<<what<< "into " << m_key << endl; + QString m = what[0]; + + if (m_subMap.find(m)==m_subMap.end()) { + m_subMap[m].m_key=m; + } + if (what.count()==1) { + // kdDebug()<<"Inserting valid key "<< m << endl; + m_subMap[m].setValidContent(m,st); + // kdDebug()<<"Inserting valid key done"<< endl; + return; + } + what.erase(what.begin()); + //kdDebug()<<"Go into loop"<<endl; + m_subMap[m].insertKey(what,st); +} + +template<class C> template<class T> inline void cacheEntry<C>::listsubs_if(QStringList&what,T&oper)const +{ + if (what.count()==0) { + /* we are the one to get the list for*/ + oper = for_each(m_subMap.begin(),m_subMap.end(),oper); + return; + } + /* otherwise find next */ + citer it = m_subMap.find(what[0]); + if (it==m_subMap.end()) { + /* not found */ + return; + } + what.erase(what.begin()); + it->second.listsubs_if(what,oper); +} + +template<class C> class itemCache +{ +public: + typedef cacheEntry<C> cache_type; + typedef typename std::map<QString,cache_type> cache_map_type; + typedef typename cache_map_type::const_iterator citer; + typedef typename cache_map_type::iterator iter; + +protected: + cache_map_type m_contentMap; + +public: + itemCache():m_contentMap(){} + virtual ~itemCache(){}; + + void setContent(const QLIST<C>&dlist); + void clear(){m_contentMap.clear();} + //! Checks if cache contains a specific item + /*! + * the keylist will manipulated - so copy-operations aren't needed. + * \param what Stringlist containing the components to search for + * \return true if found (may or may not valid!) otherwise false + */ + virtual bool find(const QString&what)const; + virtual bool find(const QString&,QLIST<C>&)const; + + virtual void deleteKey(const QString&what,bool exact); + virtual void insertKey(const C&,const QString&path); + virtual bool findSingleValid(const QString&what,C&)const; + virtual bool findSingleValid(const QString&what,bool check_valid_subs)const; + + template<class T>void listsubs_if(const QString&what,T&oper)const; + + void dump_tree(); +}; + +template<class C> inline void itemCache<C>::setContent(const QLIST<C>&dlist) +{ + m_contentMap.clear(); + citer it; + for (it=dlist.begin();it!=dlist.end();++it) { + QStringList _keys = QStringList::split("/",(*it).path()); + if (_keys.count()==0) { + continue; + } + m_contentMap[_keys[0]]=statusEntry(_keys[0]); + if (_keys.count()==1) { + m_contentMap[_keys[0]].setValidContent(_keys[0],(*it)); + } else { + _keys.erase(_keys.begin()); + m_contentMap[_keys[0]].insertKey(_keys,(*it)); + } + } +} + +template<class C> inline void itemCache<C>::insertKey(const C&st,const QString&path) +{ + // kdDebug()<<"Inserting "<<st.path()<<endl; + QStringList _keys = QStringList::split("/",path); + if (_keys.count()==0) { + return; + } + iter it=m_contentMap.find(_keys[0]); + + if (it==m_contentMap.end()) { + m_contentMap[_keys[0]]=cache_type(_keys[0]); + } + if (_keys.count()==1) { + m_contentMap[_keys[0]].setValidContent(_keys[0],st); + } else { + QString m = _keys[0]; + _keys.erase(_keys.begin()); + m_contentMap[m].insertKey(_keys,st); + } +} + +template<class C> inline bool itemCache<C>::find(const QString&what)const +{ + if (m_contentMap.size()==0) { + return false; + } + QStringList _keys = QStringList::split("/",what); + if (_keys.count()==0) { + return false; + } + citer it=m_contentMap.find(_keys[0]); + if (it==m_contentMap.end()) { + return false; + } + if (_keys.count()==1) { + return true; + } + _keys.erase(_keys.begin()); + return it->second.find(_keys); +} + +template<class C> inline bool itemCache<C>::find(const QString&_what,QLIST<C>&dlist)const +{ + if (m_contentMap.size()==0) { + return false; + } + QStringList what = QStringList::split("/",_what); + if (what.count()==0) { + return false; + } + citer it=m_contentMap.find(what[0]); + if (it==m_contentMap.end()) { + return false; + } + what.erase(what.begin()); + // kdDebug()<<"itemCache::find(const QString&_what,svn::StatusEntries&dlist) "<<what<<endl; + return it->second.find(what,dlist); +} + +template<class C> inline void itemCache<C>::deleteKey(const QString&_what,bool exact) +{ + if (m_contentMap.size()==0) { + return; + } + QStringList what = QStringList::split("/",_what); + if (what.count()==0) { + return; + } + iter it=m_contentMap.find(what[0]); + if (it==m_contentMap.end()) { + return; + } + /* first stage - we are the one holding the right key */ + if (what.count()==1){ + if (!exact || !it->second.hasValidSubs()) { + /* if it has no valid subs delete it */ + m_contentMap.erase(it); + } else { + /* otherwise mark as invalid */ + it->second.markInvalid(); + } + return; + } else { + /* otherwise go trough tree */ + what.erase(what.begin()); + bool b = it->second.deleteKey(what,exact); + if (b && !it->second.hasValidSubs()) { + m_contentMap.erase(it); + } + } +} + +template<class C> inline void itemCache<C>::dump_tree() +{ + citer it; + for (it=m_contentMap.begin();it!=m_contentMap.end();++it) { +// std::cout<<it->first.latin1() << " (" << it->second.key().latin1() << ")"<<std::endl; +// it->second.dump_tree(1); + } +} + +template<class C> inline bool itemCache<C>::findSingleValid(const QString&_what,C&st)const +{ + if (m_contentMap.size()==0) { + return false; + } + QStringList what = QStringList::split("/",_what); + if (what.count()==0) { + return false; + } + //kdDebug()<<"Itemcache What: "<<what << endl; + citer it=m_contentMap.find(what[0]); + if (it==m_contentMap.end()) { + //kdDebug()<<"Entry in cache not found"<<endl; + return false; + } + if (what.count()==1) { + if (it->second.isValid()) { + st=it->second.content(); + return true; + } + return false; + } + //kdDebug()<<"Stage down"<<endl; + what.erase(what.begin()); + return it->second.findSingleValid(what,st); +} + +template<class C> inline bool itemCache<C>::findSingleValid(const QString&_what,bool check_valid_subs)const +{ + if (m_contentMap.size()==0) { + return false; + } + QStringList what = QStringList::split("/",_what); + if (what.count()==0) { + return false; + } + citer it=m_contentMap.find(what[0]); + if (it==m_contentMap.end()) { + return false; + } + if (what.count()==1) { + return it->second.isValid()||(check_valid_subs&&it->second.hasValidSubs()); + } + what.erase(what.begin()); + return it->second.findSingleValid(what,check_valid_subs); +} + +template<class C> template<class T> inline void itemCache<C>::listsubs_if(const QString&_what,T&oper)const +{ + if (m_contentMap.size()==0) { + return; + } + QStringList what = QStringList::split("/",_what); + if (what.count()==0) { + return; + } + citer it=m_contentMap.find(what[0]); + + if (it==m_contentMap.end()) { + return; + } + if (what.count()==1) { + oper = for_each(m_contentMap.begin(),m_contentMap.end(),oper); + return; + } + what.erase(what.begin()); + it->second.listsubs_if(what,oper); +} + +typedef cacheEntry<svn::StatusPtr> ptrEntry; +typedef itemCache<svn::StatusPtr> statusCache; + +class ValidRemoteOnly +{ + svn::StatusEntries m_List; +public: + ValidRemoteOnly():m_List(){} + void operator()(const std::pair<QString,helpers::ptrEntry>&_data) + { + if(_data.second.isValid() && _data.second.content()->validReposStatus()&&!_data.second.content()->validLocalStatus()) { + m_List.push_back(_data.second.content()); + } + } + const svn::StatusEntries&liste()const{return m_List;} +}; + +} + +#endif diff --git a/src/svnfrontend/ccontextlistener.cpp b/src/svnfrontend/ccontextlistener.cpp new file mode 100644 index 0000000..a331db4 --- /dev/null +++ b/src/svnfrontend/ccontextlistener.cpp @@ -0,0 +1,353 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "ccontextlistener.h" +#include "src/settings/kdesvnsettings.h" +#include "src/ksvnwidgets/authdialogimpl.h" +#include "src/ksvnwidgets/logmsg_impl.h" +#include "src/ksvnwidgets/ssltrustprompt_impl.h" +#include "src/ksvnwidgets/pwstorage.h" + +#include <klocale.h> +#include <kapp.h> +#include <kinputdialog.h> +#include <kpassdlg.h> +#include <kdebug.h> +#include <kfiledialog.h> + +#include <qmap.h> +#include <qtextstream.h> +#include <qthread.h> + +class CContextListenerData +{ +public: + CContextListenerData(); + virtual ~CContextListenerData(); + + // data + bool m_cancelMe; + QMutex m_CancelMutex; + + bool noDialogs; +}; + +CContextListenerData::CContextListenerData() + : m_cancelMe(false),m_CancelMutex(),noDialogs(false) +{ +} + +CContextListenerData::~CContextListenerData() +{ +} + +const int CContextListener::smax_actionstring=svn_wc_notify_failed_unlock+1; + +const QString CContextListener::action_strings[]={ + I18N_NOOP("Add to revision control"), + I18N_NOOP("Copy"), + I18N_NOOP("Delete"), + I18N_NOOP("Restore missing"), + I18N_NOOP("Revert"), + I18N_NOOP("Revert failed"), + I18N_NOOP("Resolved"), + I18N_NOOP("Skip"), + I18N_NOOP("Deleted"), + I18N_NOOP("Added"), + I18N_NOOP("Update"), //svn_wc_notify_update_update + I18N_NOOP("Update complete"), + I18N_NOOP("Update external module"), + QString::null, // status completed - will not send is just noisy + I18N_NOOP("Status on external"), //svn_wc_notify_status_external + I18N_NOOP("Commit Modified"), + I18N_NOOP("Commit Added"), + I18N_NOOP("Commit Deleted"), + I18N_NOOP("Commit Replaced"), + QString::null, //tx delta -> making ticks instead + QString::null, //svn_wc_notify_blame_revision - using ticks + I18N_NOOP("Locking"), + I18N_NOOP("Unlocked"), + I18N_NOOP("Lock failed"), + I18N_NOOP("Unlock failed") +}; + +const QString CContextListener::notify_state_strings[]={ + QString::null, // = 0 + QString::null, + I18N_NOOP("unchanged"), + I18N_NOOP("item wasn't present"), + I18N_NOOP("unversioned item obstructed work"), + // I18N_NOOP("Pristine state was modified."), // should send a signal with path instead of message? + QString::null, + I18N_NOOP("Modified state had mods merged in."), + I18N_NOOP("Modified state got conflicting mods.") +}; + +QString CContextListener::NotifyAction(svn_wc_notify_action_t action) +{ + if (action>=smax_actionstring||action<0) { + return QString::null; + } + return action_strings[action].isEmpty()?QString::null:i18n(action_strings[action]); +} + +QString CContextListener::NotifyState(svn_wc_notify_state_t state) +{ + if (state > svn_wc_notify_state_conflicted || state<0) return QString::null; + return notify_state_strings[state].isEmpty()?QString::null:i18n(notify_state_strings[state]); +} + +CContextListener::CContextListener(QObject *parent, const char *name) + : QObject(parent, name), svn::ContextListener(),ref_count() +{ + m_Data = new CContextListenerData(); +} + +CContextListener::~CContextListener() +{ + disconnect(); + delete m_Data; +} + +bool CContextListener::contextGetCachedLogin (const QString & realm,QString & username,QString & password) +{ + PwStorage::self()->getCachedLogin(realm,username,password); + return true; +} + +bool CContextListener::contextGetSavedLogin (const QString & realm,QString & username,QString & password) +{ + PwStorage::self()->getLogin(realm,username,password); + PwStorage::self()->setCachedLogin(realm,username,password); + /* the return value isn't interesting to us... */ + return true; +} + +bool CContextListener::contextGetLogin ( + const QString & realm, + QString & username, + QString & password, + bool & maySave) +{ + maySave = false; + emit waitShow(true); + emit sendNotify(realm); + AuthDialogImpl auth(realm,username); + if (auth.exec()==QDialog::Accepted) { + username=auth.Username(); + password=auth.Password(); + maySave = (Kdesvnsettings::passwords_in_wallet()?false:auth.maySave()); + if (Kdesvnsettings::passwords_in_wallet() && auth.maySave()) { + PwStorage::self()->setLogin(realm,username,password); + } + if (Kdesvnsettings::use_password_cache()) { + PwStorage::self()->setCachedLogin(realm,username,password); + } + emit waitShow(false); + return true; + } + emit waitShow(false); + return false; +} + +void CContextListener::contextNotify(const QString&aMsg) +{ + if (aMsg.isEmpty()) { + emit tickProgress(); + } else { + emit sendNotify(aMsg); + } +} + +void CContextListener::contextNotify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t /* kind */, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision) +{ + QString msg; + QString aString = NotifyAction(action); + + if (!aString.isEmpty()) { + QTextStream ts(&msg,IO_WriteOnly); + ts << NotifyAction(action) << " " << QString::FROMUTF8(path); + if (revision>-1) { + ts << " (Rev "<<revision<<")"; + } + aString = NotifyState(content_state); + if (!aString.isEmpty()) { + ts << "\n" << aString; + } + } + contextNotify(msg); +} + +void CContextListener::contextNotify (const svn_wc_notify_t *action) +{ + if (!action) return; +// if (action->action<svn_wc_notify_locked) { + contextNotify(action->path,action->action,action->kind,action->mime_type, + action->content_state,action->prop_state,action->revision); +// return; +// } +// QString aString = NotifyAction(action->action); +} + +void CContextListener::sendTick() +{ + emit tickProgress(); +} + +bool CContextListener::contextCancel() +{ + { + QMutexLocker lock(&(m_Data->m_CancelMutex)); + if (m_Data->m_cancelMe) { + m_Data->m_cancelMe=false; + return true; + } + } + // otherwise deadlock! + sendTick(); + return false; +} + +bool CContextListener::contextGetLogMessage (QString & msg,const svn::CommitItemList&items) +{ + bool isOk = false; + emit waitShow(true); + QString logMessage = Logmsg_impl::getLogmessage(items,&isOk,0,0,0); + if (isOk) { + msg = logMessage; + } + emit waitShow(false); + return isOk; +} + +svn::ContextListener::SslServerTrustAnswer CContextListener::contextSslServerTrustPrompt ( + const svn::ContextListener::SslServerTrustData & data , apr_uint32_t & acceptedFailures ) +{ + bool ok,saveit; + emit waitShow(true); + if (!SslTrustPrompt_impl::sslTrust( + data.hostname, + data.fingerprint, + data.validFrom, + data.validUntil, + data.issuerDName, + data.realm, + failure2Strings(acceptedFailures), + &ok,&saveit)) { + return DONT_ACCEPT; + } + emit waitShow(false); + if (!saveit) { + return ACCEPT_TEMPORARILY; + } + return ACCEPT_PERMANENTLY; +} + +bool CContextListener::contextSslClientCertPrompt (QString & certFile) +{ + kdDebug()<<"CContextListener::contextSslClientCertPrompt " + << certFile << endl; + emit waitShow(true); + QString afile = KFileDialog::getOpenFileName(QString::null, + QString::null, + 0, + i18n("Open a file with a #PKCS12 certificate")); + emit waitShow(false); + if (afile.isEmpty()) { + return false; + } + certFile = afile; + return true; +} + +bool CContextListener::contextLoadSslClientCertPw(QString&password,const QString&realm) +{ + PwStorage::self()->getCertPw(realm,password); + return true; +} + +bool CContextListener::contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maysave) +{ + maysave = false; + emit waitShow(true); + QCString npass; + int keep = 1; + int res = KPasswordDialog::getPassword(npass, + i18n("Enter password for realm %1").arg(realm), + &keep); + emit waitShow(false); + if (res!=KPasswordDialog::Accepted) { + return false; + } + maysave = (Kdesvnsettings::passwords_in_wallet()?false:keep!=0); + if (Kdesvnsettings::store_passwords() && keep) { + PwStorage::self()->setCertPw(realm,password); + } + password = npass; + return true; +} + +void CContextListener::setCanceled(bool how) +{ + QMutexLocker lock(&(m_Data->m_CancelMutex)); + m_Data->m_cancelMe = how; +} + +QStringList CContextListener::failure2Strings(apr_uint32_t acceptedFailures) +{ + QStringList res; + if (acceptedFailures&SVN_AUTH_SSL_UNKNOWNCA) { + res << i18n("The certificate is not issued by a trusted authority. Use the fingerprint to validate the certificate manually!"); + } + if (acceptedFailures&SVN_AUTH_SSL_CNMISMATCH) { + res<< i18n("The certificate hostname does not match."); + } + if (acceptedFailures&SVN_AUTH_SSL_NOTYETVALID) { + res << i18n("The certificate is not yet valid."); + } + if (acceptedFailures& SVN_AUTH_SSL_EXPIRED) { + res << i18n("The certificate has expired."); + } + if (acceptedFailures&SVN_AUTH_SSL_OTHER) { + res << i18n("The certificate has an unknown error."); + } + return res; +} + +QString CContextListener::translate(const QString&what) +{ + return i18n(what); +} + +/*! + \fn CContextListener::contextProgress(long long int current, long long int max) + */ +void CContextListener::contextProgress(long long int current, long long int max) +{ + emit netProgress(current,max); +} + +#include "ccontextlistener.moc" diff --git a/src/svnfrontend/ccontextlistener.h b/src/svnfrontend/ccontextlistener.h new file mode 100644 index 0000000..216243b --- /dev/null +++ b/src/svnfrontend/ccontextlistener.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CCONTEXTLISTENER_H +#define CCONTEXTLISTENER_H + +#include "src/svnqt/context_listener.hpp" +#include "src/svnqt/smart_pointer.hpp" + +#include <qobject.h> +#include <qstring.h> + +class CContextListenerData; + +/** +@author Rajko Albrecht +*/ +class CContextListener : public QObject, public svn::ContextListener,public svn::ref_count +{ + Q_OBJECT +public: + CContextListener(QObject *parent = 0, const char *name = 0); + virtual ~CContextListener(); + + /* context-listener methods */ + virtual bool contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave); + virtual bool contextGetSavedLogin (const QString & realm,QString & username,QString & password); + virtual bool contextGetCachedLogin(const QString & realm,QString & username,QString & password); + + + virtual void contextNotify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision); + virtual void contextNotify(const QString&aMsg); + virtual void sendTick(); + virtual void contextNotify (const svn_wc_notify_t *action); + + virtual bool contextCancel(); + /*! + * Get logmessage for checkin and so on... + */ + virtual bool contextGetLogMessage (QString & msg,const svn::CommitItemList&); + virtual SslServerTrustAnswer contextSslServerTrustPrompt (const SslServerTrustData & data, + apr_uint32_t & acceptedFailures); + virtual bool contextSslClientCertPrompt (QString & certFile); + virtual bool contextSslClientCertPwPrompt (QString & password, + const QString & realm, bool & maySave); + virtual bool contextLoadSslClientCertPw(QString&password,const QString&realm); + virtual QString translate(const QString&what); + + static QString NotifyAction(svn_wc_notify_action_t action); + static QString NotifyState(svn_wc_notify_state_t); + + static QStringList failure2Strings(apr_uint32_t acceptedFailures); + virtual void contextProgress(long long int current, long long int max); + +public slots: + virtual void setCanceled(bool); + +signals: + void sendNotify(const QString&); + void tickProgress(); + void waitShow(bool); + void netProgress(long long int, long long int); + +protected: + static const int smax_actionstring; + static const QString action_strings[]; + static const QString notify_state_strings[]; + CContextListenerData*m_Data; +}; + +#endif diff --git a/src/svnfrontend/commandexec.cpp b/src/svnfrontend/commandexec.cpp new file mode 100644 index 0000000..86638de --- /dev/null +++ b/src/svnfrontend/commandexec.cpp @@ -0,0 +1,650 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "commandexec.h" +#include "src/settings/kdesvnsettings.h" +#include "svnfrontend/svnactions.h" +#include "svnfrontend/dummydisplay.h" +#include "src/svnqt/targets.hpp" +#include "src/svnqt/url.hpp" +#include "src/svnqt/dirent.hpp" +#include "src/helpers/sub2qt.h" +#include "src/helpers/ktranslateurl.h" +#include "src/helpers/sshagent.h" +#include "src/svnfrontend/fronthelpers/rangeinput_impl.h" +#include "src/svnfrontend/copymoveview_impl.h" + +#include <kapp.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <kdialogbase.h> +#include <ktextbrowser.h> + +#include <qfile.h> +#include <qtextstream.h> +#include <qvaluelist.h> +#include <qvbox.h> + +class pCPart +{ +public: + pCPart(); + ~pCPart(); + + QString cmd; + QStringList url; + bool ask_revision; + bool rev_set; + bool outfile_set; + bool single_revision; + bool force; + int log_limit; + SvnActions*m_SvnWrapper; + KCmdLineArgs *args; + svn::Revision start,end; + + // for output + QFile toStdout,toStderr; + QString outfile; + QTextStream Stdout,Stderr; + DummyDisplay * disp; + QMap<int,svn::Revision> extraRevisions; + QMap<int,QString> baseUrls; +}; + +pCPart::pCPart() + :cmd(""),url(),ask_revision(false),rev_set(false),outfile_set(false),single_revision(false),log_limit(0) +{ + m_SvnWrapper = 0; + start = svn::Revision::UNDEFINED; + end = svn::Revision::UNDEFINED; + toStdout.open(IO_WriteOnly, stdout); + toStderr.open(IO_WriteOnly, stderr); + Stdout.setDevice(&toStdout); + Stderr.setDevice(&toStderr); + disp = new DummyDisplay(); + m_SvnWrapper = new SvnActions(disp,0,true); +} + +pCPart::~pCPart() +{ + delete m_SvnWrapper; + delete disp; +} + +CommandExec::CommandExec(QObject*parent, const char *name,KCmdLineArgs *args) + : QObject(parent,name) +{ + m_pCPart = new pCPart; + m_pCPart->args = args; + SshAgent ag; + ag.querySshAgent(); + + connect(m_pCPart->m_SvnWrapper,SIGNAL(clientException(const QString&)),this,SLOT(clientException(const QString&))); + connect(m_pCPart->m_SvnWrapper,SIGNAL(sendNotify(const QString&)),this,SLOT(slotNotifyMessage(const QString&))); + m_pCPart->m_SvnWrapper->reInitClient(); +} + + +CommandExec::~CommandExec() +{ + delete m_pCPart; +} + +int CommandExec::exec() +{ + if (!m_pCPart->args) { + return -1; + } + m_lastMessages = ""; + m_lastMessagesLines = 0; + m_pCPart->m_SvnWrapper->reInitClient(); + bool dont_check_second = false; + bool dont_check_all = false; + bool path_only = false; + bool no_revision = false; + bool check_force=false; + + if (m_pCPart->args->count()>=2) { + m_pCPart->cmd=m_pCPart->args->arg(1); + m_pCPart->cmd=m_pCPart->cmd.lower(); + } + QString slotCmd; + if (!QString::compare(m_pCPart->cmd,"log")) { + slotCmd=SLOT(slotCmd_log()); + } else if (!QString::compare(m_pCPart->cmd,"cat")) { + slotCmd=SLOT(slotCmd_cat()); + m_pCPart->single_revision=true; + } else if (!QString::compare(m_pCPart->cmd,"get")) { + slotCmd=SLOT(slotCmd_get()); + m_pCPart->single_revision=true; + } else if (!QString::compare(m_pCPart->cmd,"help")) { + slotCmd=SLOT(slotCmd_help()); + } else if (!QString::compare(m_pCPart->cmd,"blame")|| + !QString::compare(m_pCPart->cmd,"annotate")) { + slotCmd=SLOT(slotCmd_blame()); + } else if (!QString::compare(m_pCPart->cmd,"update")) { + slotCmd=SLOT(slotCmd_update()); + m_pCPart->single_revision=true; + } else if (!QString::compare(m_pCPart->cmd,"diff")) { + m_pCPart->start = svn::Revision::WORKING; + slotCmd=SLOT(slotCmd_diff()); + } else if (!QString::compare(m_pCPart->cmd,"info")) { + slotCmd=SLOT(slotCmd_info()); + m_pCPart->single_revision=true; + } else if (!QString::compare(m_pCPart->cmd,"commit")|| + !QString::compare(m_pCPart->cmd,"ci")) { + slotCmd=SLOT(slotCmd_commit()); + } else if (!QString::compare(m_pCPart->cmd,"list")|| + !QString::compare(m_pCPart->cmd,"ls")) { + slotCmd=SLOT(slotCmd_list()); + } else if (!QString::compare(m_pCPart->cmd,"copy")|| + !QString::compare(m_pCPart->cmd,"cp")) { + slotCmd=SLOT(slotCmd_copy()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"move")|| + !QString::compare(m_pCPart->cmd,"rename")|| + !QString::compare(m_pCPart->cmd,"mv")) { + slotCmd=SLOT(slotCmd_move()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"checkout")|| + !QString::compare(m_pCPart->cmd,"co")) { + slotCmd=SLOT(slotCmd_checkout()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"checkoutto")|| + !QString::compare(m_pCPart->cmd,"coto")) { + slotCmd=SLOT(slotCmd_checkoutto()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"export")) { + slotCmd=SLOT(slotCmd_export()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"exportto")) { + slotCmd=SLOT(slotCmd_exportto()); + dont_check_second = true; + } else if (!QString::compare(m_pCPart->cmd,"delete")|| + !QString::compare(m_pCPart->cmd,"del")|| + !QString::compare(m_pCPart->cmd,"rm")|| + !QString::compare(m_pCPart->cmd,"remove")) { + slotCmd=SLOT(slotCmd_delete()); + } else if (!QString::compare(m_pCPart->cmd,"add")) { + slotCmd=SLOT(slotCmd_add()); + dont_check_all = true; + path_only=true; + } else if (!QString::compare(m_pCPart->cmd,"undo")|| + !QString::compare(m_pCPart->cmd,"revert")) { + slotCmd=SLOT(slotCmd_revert()); + } else if (!QString::compare(m_pCPart->cmd,"checknew")|| + !QString::compare(m_pCPart->cmd,"addnew")) { + slotCmd=SLOT(slotCmd_addnew()); + } else if (!QString::compare(m_pCPart->cmd,"switch")) { + slotCmd=SLOT(slotCmd_switch()); + } else if (!QString::compare(m_pCPart->cmd,"tree")) { + slotCmd=SLOT(slotCmd_tree()); + } else if (!QString::compare(m_pCPart->cmd,"lock")) { + slotCmd=SLOT(slotCmd_lock()); + no_revision = true; + check_force=true; + } else if (!QString::compare(m_pCPart->cmd,"unlock")) { + slotCmd=SLOT(slotCmd_unlock()); + no_revision=true; + check_force=true; + } + + bool found = connect(this,SIGNAL(executeMe()),this,slotCmd.ascii()); + if (!found) { + slotCmd=i18n("Command \"%1\" not implemented or known").arg(m_pCPart->cmd); + KMessageBox::sorry(0,slotCmd,i18n("SVN Error")); + return -1; + } + + QString tmp,query,proto,v; + QMap<QString,QString> q; + + KURL tmpurl; + QString mainProto; + QString _baseurl; + for (int j = 2; j<m_pCPart->args->count();++j) { + tmpurl = helpers::KTranslateUrl::translateSystemUrl(m_pCPart->args->url(j).prettyURL()); + query = tmpurl.query(); + q = m_pCPart->args->url(j).queryItems(); + if (q.find("rev")!=q.end()) { + v = q["rev"]; + } else { + v = ""; + } + tmpurl.setProtocol(svn::Url::transformProtokoll(tmpurl.protocol())); + if (tmpurl.protocol().find("ssh")!=-1) { + SshAgent ag; + // this class itself checks if done before + ag.addSshIdentities(); + } + m_pCPart->extraRevisions[j-2]=svn::Revision::HEAD; + + if (tmpurl.isLocalFile() && (j==2 || !dont_check_second) && !dont_check_all) { + if (m_pCPart->m_SvnWrapper->isLocalWorkingCopy("file://"+tmpurl.path(),_baseurl)) { + tmp = tmpurl.path(); + m_pCPart->baseUrls[j-2]=_baseurl; + m_pCPart->extraRevisions[j-2]=svn::Revision::WORKING; + if (j==2) mainProto = ""; + } else { + tmp = "file://"+tmpurl.path(); + if (j==2) mainProto = "file://"; + } + } else if (path_only){ + tmp = tmpurl.path(); + } else { + tmp = tmpurl.url(); + if (j==2) mainProto=tmpurl.protocol(); + } + if ( (j>2 && dont_check_second) || dont_check_all) { + if (mainProto.isEmpty()) { + tmp = tmpurl.path(); + } + } + QStringList l = QStringList::split('?',tmp); + if (l.count()>0) { + tmp=l[0]; + } + while (tmp.endsWith("/")) { + tmp.truncate(tmp.length()-1); + } + m_pCPart->url.append(tmp); + if ( (j>2 && dont_check_second) || dont_check_all) { + continue; + } + svn::Revision re = v; + if (re) { + m_pCPart->extraRevisions[j-2]=re; + } + } + if (m_pCPart->url.count()==0) { + m_pCPart->url.append("."); + } + + if (!no_revision) + { + if (m_pCPart->args->isSet("R")) + { + m_pCPart->ask_revision = true; + if (!askRevision()) + { + return 0; + } + } + else if (m_pCPart->args->isSet("r")) + { + scanRevision(); + } + } + + m_pCPart->force=check_force && m_pCPart->args->isSet("f"); + + if (m_pCPart->args->isSet("o")) { + m_pCPart->outfile_set=true; + m_pCPart->outfile = m_pCPart->args->getOption("o"); + } + if (m_pCPart->args->isSet("l")) { + QString s = m_pCPart->args->getOption("l"); + m_pCPart->log_limit = s.toInt(); + if (m_pCPart->log_limit<0) { + m_pCPart->log_limit = 0; + } + } + + emit executeMe(); + if (Kdesvnsettings::self()->cmdline_show_logwindow() && + m_lastMessagesLines >= Kdesvnsettings::self()->cmdline_log_minline()) { + KDialogBase dlg ( + KApplication::activeModalWidget(), + "execution_log", + true, + i18n("Execution log"), + KDialogBase::Ok); + + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + KTextBrowser*ptr = new KTextBrowser(Dialog1Layout); + ptr->setText(m_lastMessages); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),"kdesvn_cmd_log")); + dlg.exec(); + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"kdesvn_cmd_log",false); + } + return 0; +} + + + +/*! + \fn CommandExec::clientException(const QString&) + */ +void CommandExec::clientException(const QString&what) +{ + m_pCPart->Stderr<<what<<endl; + KMessageBox::sorry(0,what,i18n("SVN Error")); +} + + +/*! + \fn CommandExec::slotCmdLog + */ +void CommandExec::slotCmd_log() +{ + int limit = m_pCPart->log_limit; + if (m_pCPart->end == svn::Revision::UNDEFINED) { + m_pCPart->end = svn::Revision::HEAD; + limit = 0; + } + if (m_pCPart->start == svn::Revision::UNDEFINED) { + m_pCPart->start = 1; + limit = 0; + } + bool list = Kdesvnsettings::self()->log_always_list_changed_files(); + if (m_pCPart->extraRevisions[0]==svn::Revision::WORKING) { + m_pCPart->extraRevisions[0]=svn::Revision::UNDEFINED; + } + m_pCPart->m_SvnWrapper->makeLog(m_pCPart->start,m_pCPart->end,m_pCPart->extraRevisions[0],m_pCPart->url[0],list,limit); +} + +/*! + \fn CommandExec::slotCmdLog + */ +void CommandExec::slotCmd_tree() +{ + if (m_pCPart->end == svn::Revision::UNDEFINED) { + m_pCPart->end = svn::Revision::HEAD; + } + if (m_pCPart->start == svn::Revision::UNDEFINED) { + m_pCPart->start = 1; + } + m_pCPart->m_SvnWrapper->makeTree(m_pCPart->url[0],m_pCPart->extraRevisions[0],m_pCPart->start,m_pCPart->end); +} + +void CommandExec::slotCmd_checkout() +{ + m_pCPart->m_SvnWrapper->CheckoutExport(m_pCPart->url[0],false); +} + +void CommandExec::slotCmd_checkoutto() +{ + m_pCPart->m_SvnWrapper->CheckoutExport(m_pCPart->url[0],false,true); +} + +void CommandExec::slotCmd_export() +{ + m_pCPart->m_SvnWrapper->CheckoutExport(m_pCPart->url[0],true); +} + +void CommandExec::slotCmd_exportto() +{ + m_pCPart->m_SvnWrapper->CheckoutExport(m_pCPart->url[0],true,true); +} + +void CommandExec::slotCmd_blame() +{ + if (!m_pCPart->end) { + m_pCPart->end = svn::Revision::HEAD; + } + if (!m_pCPart->start) { + m_pCPart->start = 1; + } + m_pCPart->m_SvnWrapper->makeBlame(m_pCPart->start,m_pCPart->end,m_pCPart->url[0]); +} + +void CommandExec::slotCmd_cat() +{ + if (m_pCPart->extraRevisions.find(0)!=m_pCPart->extraRevisions.end()) { + m_pCPart->rev_set=true; + m_pCPart->start=m_pCPart->extraRevisions[0]; + } else { + m_pCPart->end = svn::Revision::HEAD; + } + m_pCPart->m_SvnWrapper->slotMakeCat( + (m_pCPart->rev_set?m_pCPart->start:m_pCPart->end),m_pCPart->url[0],m_pCPart->url[0] + ,(m_pCPart->rev_set?m_pCPart->start:m_pCPart->end),0); +} + +void CommandExec::slotCmd_get() +{ + if (m_pCPart->extraRevisions.find(0)!=m_pCPart->extraRevisions.end()) { + m_pCPart->rev_set=true; + m_pCPart->start=m_pCPart->extraRevisions[0]; + } else { + m_pCPart->end = svn::Revision::HEAD; + } + if (!m_pCPart->outfile_set || m_pCPart->outfile.isEmpty()) { + clientException(i18n("\"GET\" requires output file!")); + return; + } + m_pCPart->m_SvnWrapper->makeGet((m_pCPart->rev_set?m_pCPart->start:m_pCPart->end),m_pCPart->url[0], m_pCPart->outfile, + (m_pCPart->rev_set?m_pCPart->start:m_pCPart->end)); +} + +void CommandExec::slotCmd_update() +{ + m_pCPart->m_SvnWrapper->makeUpdate(m_pCPart->url, + (m_pCPart->rev_set?m_pCPart->start:svn::Revision::HEAD),true); +} + +void CommandExec::slotCmd_diff() +{ + if (m_pCPart->url.count()==1) { + if (!m_pCPart->rev_set && !svn::Url::isValid(m_pCPart->url[0])) { + m_pCPart->start = svn::Revision::BASE; + m_pCPart->end = svn::Revision::WORKING; + } + m_pCPart->m_SvnWrapper->makeDiff(m_pCPart->url[0],m_pCPart->start,m_pCPart->url[0],m_pCPart->end); + } else { + svn::Revision r1 = svn::Revision::HEAD; + svn::Revision r2 = svn::Revision::HEAD; + if (m_pCPart->extraRevisions.find(0)!=m_pCPart->extraRevisions.end()) { + r1 = m_pCPart->extraRevisions[0]; + } else if (!svn::Url::isValid(m_pCPart->url[0])) { + r1 = svn::Revision::WORKING; + } + if (m_pCPart->extraRevisions.find(1)!=m_pCPart->extraRevisions.end()) { + r2 = m_pCPart->extraRevisions[1]; + } else if (!svn::Url::isValid(m_pCPart->url[1])) { + r2 = svn::Revision::WORKING; + } + m_pCPart->m_SvnWrapper->makeDiff(m_pCPart->url[0],r1,m_pCPart->url[1],r2); + } +} + +void CommandExec::slotCmd_info() +{ + if (m_pCPart->extraRevisions.find(0)!=m_pCPart->extraRevisions.end()) { + m_pCPart->rev_set=true; + m_pCPart->start=m_pCPart->extraRevisions[0]; + } + m_pCPart->m_SvnWrapper->makeInfo(m_pCPart->url,(m_pCPart->rev_set?m_pCPart->start:m_pCPart->end),svn::Revision::UNDEFINED,false); +} + +void CommandExec::slotCmd_commit() +{ + QValueList<svn::Path> targets; + for (unsigned j=0; j<m_pCPart->url.count();++j) { + targets.push_back(svn::Path(m_pCPart->url[j])); + } + m_pCPart->m_SvnWrapper->makeCommit(svn::Targets(targets)); +} + +void CommandExec::slotCmd_list() +{ + svn::DirEntries res; + svn::Revision rev = m_pCPart->end; + if (m_pCPart->rev_set){ + rev = m_pCPart->start; + } else if (m_pCPart->extraRevisions[0]) { + rev = m_pCPart->extraRevisions[0]; + } + if (!m_pCPart->m_SvnWrapper->makeList(m_pCPart->url[0],res,rev,false)) { + return; + } + for (unsigned int i = 0; i < res.count();++i) { + QString d = svn::DateTime(res[i]->time()).toString(QString("yyyy-MM-dd hh:mm::ss")); + m_pCPart->Stdout + << (res[i]->kind()==svn_node_dir?"D":"F")<<" " + << d << " " + << res[i]->name()<<endl; + } +} + +void CommandExec::slotCmd_copy() +{ + QString target; + if (m_pCPart->url.count()<2) { + bool force_move,ok; + target = CopyMoveView_impl::getMoveCopyTo(&ok,&force_move,false, + m_pCPart->url[0],"",0,"move_name"); + if (!ok) { + return; + } + } else { + target = m_pCPart->url[1]; + } + if (m_pCPart->extraRevisions.find(0)!=m_pCPart->extraRevisions.end()) { + m_pCPart->rev_set=true; + m_pCPart->start=m_pCPart->extraRevisions[0]; + } else { + m_pCPart->end = svn::Revision::HEAD; + } + m_pCPart->m_SvnWrapper->makeCopy(m_pCPart->url[0],target,(m_pCPart->rev_set?m_pCPart->start:m_pCPart->end)); +} + +void CommandExec::slotCmd_move() +{ + bool force_move,ok; + force_move = false; + QString target; + if (m_pCPart->url.count()<2) { + target = CopyMoveView_impl::getMoveCopyTo(&ok,&force_move,true, + m_pCPart->url[0],"",0,"move_name"); + if (!ok) { + return; + } + } else { + target = m_pCPart->url[1]; + } + m_pCPart->m_SvnWrapper->makeMove(m_pCPart->url[0],target,force_move); +} + +void CommandExec::slotCmd_delete() +{ + m_pCPart->m_SvnWrapper->makeDelete(m_pCPart->url); +} + +void CommandExec::slotCmd_add() +{ + m_pCPart->m_SvnWrapper->addItems(m_pCPart->url,svn::DepthInfinity); +} + +void CommandExec::slotCmd_revert() +{ + m_pCPart->m_SvnWrapper->slotRevertItems(m_pCPart->url); +} + +void CommandExec::slotCmd_addnew() +{ + m_pCPart->m_SvnWrapper->checkAddItems(m_pCPart->url[0]); +} + +/*! + \fn CommandExec::scanRevision() + */ +bool CommandExec::scanRevision() +{ + QString revstring = m_pCPart->args->getOption("r"); + QStringList revl = QStringList::split(":",revstring); + if (revl.count()==0) { + return false; + } + m_pCPart->start = revl[0]; + if (revl.count()>1) { + m_pCPart->end = revl[1]; + } + m_pCPart->rev_set=true; + return true; +} + +void CommandExec::slotNotifyMessage(const QString&msg) +{ + m_pCPart->m_SvnWrapper->slotExtraLogMsg(msg); + if (Kdesvnsettings::self()->cmdline_show_logwindow()) { + ++m_lastMessagesLines; + if (!m_lastMessages.isEmpty()) m_lastMessages.append("\n"); + m_lastMessages.append(msg); + } +} + +bool CommandExec::askRevision() +{ + QString _head = m_pCPart->cmd+" - Revision"; + KDialogBase dlg( + 0, + "Revisiondlg", + true, + _head, + KDialogBase::Ok|KDialogBase::Cancel); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + Rangeinput_impl*rdlg; + rdlg = new Rangeinput_impl(Dialog1Layout); + dlg.resize( QSize(120,60).expandedTo(dlg.minimumSizeHint())); + rdlg->setStartOnly(m_pCPart->single_revision); + if (dlg.exec()==QDialog::Accepted) { + Rangeinput_impl::revision_range range = rdlg->getRange(); + m_pCPart->start = range.first; + m_pCPart->end = range.second; + m_pCPart->rev_set = true; + return true; + } + return false; +} + + +/*! + \fn CommandExec::slotCmd_switch() + */ +void CommandExec::slotCmd_switch() +{ + QString base; + if (m_pCPart->url.count()>1) { + clientException(i18n("May only switch one url at time!")); + return; + } + if (m_pCPart->baseUrls.find(0)==m_pCPart->baseUrls.end()) { + clientException(i18n("Switch only on working copies!")); + return; + } + base = m_pCPart->baseUrls[0]; + m_pCPart->m_SvnWrapper->makeSwitch(m_pCPart->url[0],base); +} + +void CommandExec::slotCmd_lock() +{ + m_pCPart->m_SvnWrapper->makeLock(m_pCPart->url[0],"",m_pCPart->force); +} + +void CommandExec::slotCmd_unlock() +{ + m_pCPart->m_SvnWrapper->makeUnlock(m_pCPart->url[0],m_pCPart->force); +} + +#include "commandexec.moc" diff --git a/src/svnfrontend/commandexec.h b/src/svnfrontend/commandexec.h new file mode 100644 index 0000000..bd8f16e --- /dev/null +++ b/src/svnfrontend/commandexec.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef COMMANDEXEC_H +#define COMMANDEXEC_H + +#include <qobject.h> +#include <qstring.h> + +class KCmdLineArgs; +class KURL; +class pCPart; + +namespace svn { + class Revision; +} + +/** +@author Rajko Albrecht +*/ +class CommandExec : public QObject +{ +Q_OBJECT +public: + CommandExec(QObject*parent,const char *name,KCmdLineArgs *args); + virtual ~CommandExec(); + virtual int exec(); + +protected slots: + virtual void clientException(const QString&); + virtual void slotNotifyMessage(const QString&); + virtual void slotCmd_log(); + virtual void slotCmd_update(); + virtual void slotCmd_diff(); + virtual void slotCmd_blame(); + virtual void slotCmd_info(); + virtual void slotCmd_commit(); + virtual void slotCmd_cat(); + virtual void slotCmd_get(); + virtual void slotCmd_list(); + virtual void slotCmd_copy(); + virtual void slotCmd_move(); + virtual void slotCmd_checkout(); + virtual void slotCmd_checkoutto(); + virtual void slotCmd_export(); + virtual void slotCmd_exportto(); + virtual void slotCmd_delete(); + virtual void slotCmd_add(); + virtual void slotCmd_revert(); + virtual void slotCmd_addnew(); + virtual void slotCmd_tree(); + virtual void slotCmd_lock(); + virtual void slotCmd_unlock(); + +signals: + void executeMe(); +protected: + virtual bool scanRevision(); + virtual bool askRevision(); + + QString m_lastMessages; + unsigned int m_lastMessagesLines; + +private: + pCPart*m_pCPart; + +protected slots: + void slotCmd_switch(); +}; + +#endif diff --git a/src/svnfrontend/copymoveview.ui b/src/svnfrontend/copymoveview.ui new file mode 100644 index 0000000..260f333 --- /dev/null +++ b/src/svnfrontend/copymoveview.ui @@ -0,0 +1,102 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CopyMoveView</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CopyMoveView</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>571</width> + <height>353</height> + </rect> + </property> + <property name="caption"> + <string>Copy / Move</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_HeadOneLabel</cstring> + </property> + <property name="text"> + <string><p align="right">Rename</p></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="KSqueezedTextLabel"> + <property name="name"> + <cstring>m_OldNameLabel</cstring> + </property> + <property name="text"> + <string>this long text</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>m_HeadTwoLabel</cstring> + </property> + <property name="text"> + <string>to</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KSqueezedTextLabel" row="0" column="0"> + <property name="name"> + <cstring>m_PrefixLabel</cstring> + </property> + <property name="text"> + <string>/there/</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>m_NewNameInput</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_ForceBox</cstring> + </property> + <property name="text"> + <string>Force operation</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>ksqueezedtextlabel.h</includehint> + <includehint>ksqueezedtextlabel.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/copymoveview_impl.cpp b/src/svnfrontend/copymoveview_impl.cpp new file mode 100644 index 0000000..24d3114 --- /dev/null +++ b/src/svnfrontend/copymoveview_impl.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "copymoveview_impl.h" +#include <ksqueezedtextlabel.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <klineedit.h> +#include <klocale.h> +#include <kdialogbase.h> +#include <qvbox.h> + +CopyMoveView_impl::CopyMoveView_impl(const QString&baseName,const QString&sourceName,bool move,QWidget* parent, const char* name, WFlags fl) +: CopyMoveView(parent,name,fl) +{ + m_BaseName = baseName; + if (m_BaseName.length()>0 && !m_BaseName.endsWith("/")) { + m_BaseName+="/"; + } + m_PrefixLabel->setText(m_BaseName); + m_OldNameLabel->setText("<b>"+sourceName+"</b>"); + m_OldName = sourceName; + if (m_BaseName.length()>0) { + QString t = m_OldName.right(m_OldName.length()-m_BaseName.length()); + m_NewNameInput->setText(t); + } else { + m_PrefixLabel->hide(); + m_NewNameInput->setText(sourceName); + } + if (move) { + m_HeadOneLabel->setText(i18n("Rename/move")); + } else { + m_HeadOneLabel->setText(i18n("Copy")); + m_ForceBox->hide(); + } +} + +CopyMoveView_impl::~CopyMoveView_impl() +{ +} + + +/*! + \fn CopyMoveView_impl::newName() + */ +QString CopyMoveView_impl::newName() +{ + return m_BaseName+m_NewNameInput->text(); +} + + +/*! + \fn CopyMoveView_impl::force() + */ +bool CopyMoveView_impl::force() +{ + return m_ForceBox->isChecked(); +} + + +/*! + \fn CopyMoveView_impl::getMoveCopyTo(bool*ok,bool*force,const QString&old,const QString&base,QWidget*) + */ +QString CopyMoveView_impl::getMoveCopyTo(bool*ok,bool*force,bool move, + const QString&old,const QString&base,QWidget*parent,const char*name) +{ + KDialogBase dlg(parent,name,true,(move?i18n("Move/Rename file/dir"):i18n("Copy file/dir")), + KDialogBase::Ok|KDialogBase::Cancel, + KDialogBase::NoDefault); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + CopyMoveView_impl*ptr=new CopyMoveView_impl(base,old,(move),Dialog1Layout); + QString nName = QString::null; + dlg.resize( QSize(500,160).expandedTo(dlg.minimumSizeHint()) ); + if (dlg.exec()!=QDialog::Accepted) { + if (ok) *ok = false; + } else { + if (force) *force = ptr->force(); + nName = ptr->newName(); + if (ok) *ok=true; + } + return nName; +} + +#include "copymoveview_impl.moc" diff --git a/src/svnfrontend/copymoveview_impl.h b/src/svnfrontend/copymoveview_impl.h new file mode 100644 index 0000000..2c17fd1 --- /dev/null +++ b/src/svnfrontend/copymoveview_impl.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef COPYMOVEVIEW_IMPL_H +#define COPYMOVEVIEW_IMPL_H + +#include "copymoveview.h" + +class CopyMoveView_impl : public CopyMoveView +{ + Q_OBJECT + +public: + CopyMoveView_impl(const QString&baseName,const QString&sourceName,bool move,QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~CopyMoveView_impl(); + virtual QString newName(); + bool force(); + static QString getMoveCopyTo(bool*ok,bool*force,bool move, const QString&old,const QString&base, + QWidget*,const char*name); + /*$PUBLIC_FUNCTIONS$*/ + +public slots: + /*$PUBLIC_SLOTS$*/ + +protected: + /*$PROTECTED_FUNCTIONS$*/ + +protected slots: + /*$PROTECTED_SLOTS$*/ + +protected: + QString m_OldName; + QString m_BaseName; +}; + +#endif + diff --git a/src/svnfrontend/createrepo_dlg.ui b/src/svnfrontend/createrepo_dlg.ui new file mode 100644 index 0000000..f2b2440 --- /dev/null +++ b/src/svnfrontend/createrepo_dlg.ui @@ -0,0 +1,207 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CreateRepo_Dlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CreateRepo_Dlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>344</width> + <height>218</height> + </rect> + </property> + <property name="caption"> + <string>Create new repository</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </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="text"> + <string>Type of repository:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>FSFS</string> + </property> + </item> + <item> + <property name="text"> + <string>BDB</string> + </property> + </item> + <property name="name"> + <cstring>m_FilesystemSelector</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>Select type of storage</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Select the storage type of repository (FSFS or Berkely DB)</string> + </property> + </widget> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_ReposPathinput</cstring> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Path to repository:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_DisableFsync</cstring> + </property> + <property name="text"> + <string>Disable fsync at commit (BDB only)</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_LogKeep</cstring> + </property> + <property name="text"> + <string>Disable automatic log file removal (BDB only)</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_CreateMainDirs</cstring> + </property> + <property name="text"> + <string>Create main folders</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Create trunk, tags and branches folder</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If this is set then the base layout (<tt>/trunk</tt>,<tt>/branches</tt> and <tt>/tags</tt>) will created after opening the fresh repository.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_svn13compat</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Compatible to subversion prior 1.4</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Is created repository compatible to subversion prior 1.4</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If set, the repository created will compatible to subversion prior 1.4. This is only usefull when svnqt is running with subversion 1.4 or above.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_svn14compat</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Compatible to subversion prior 1.5</string> + </property> + <property name="toolTip" stdset="0"> + <string>Is created repository compatible to subversion prior 1.5</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If set, the repository created will compatible to subversion prior 1.5. This is only usefull when svnqt is running with subversion 1.5 or above.</string> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_FilesystemSelector</sender> + <signal>activated(int)</signal> + <receiver>CreateRepo_Dlg</receiver> + <slot>fsTypeChanged(int)</slot> + </connection> + <connection> + <sender>m_svn13compat</sender> + <signal>toggled(bool)</signal> + <receiver>CreateRepo_Dlg</receiver> + <slot>compatChanged13(bool)</slot> + </connection> + <connection> + <sender>m_svn14compat</sender> + <signal>toggled(bool)</signal> + <receiver>CreateRepo_Dlg</receiver> + <slot>compatChanged14(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_ReposPathinput</tabstop> + <tabstop>m_FilesystemSelector</tabstop> + <tabstop>m_DisableFsync</tabstop> + <tabstop>m_LogKeep</tabstop> + <tabstop>m_CreateMainDirs</tabstop> + <tabstop>m_svn13compat</tabstop> + <tabstop>m_svn14compat</tabstop> +</tabstops> +<slots> + <slot access="protected">fsTypeChanged(int)</slot> + <slot access="protected">compatChanged13(bool)</slot> + <slot access="protected">compatChanged14(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/createrepo_impl.cpp b/src/svnfrontend/createrepo_impl.cpp new file mode 100644 index 0000000..160f0ab --- /dev/null +++ b/src/svnfrontend/createrepo_impl.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnfrontend/createrepo_impl.h" + +#include <kdebug.h> +#include <kurl.h> +#include <kurlrequester.h> +#include <kcombobox.h> + +#include <qcheckbox.h> + +class RecurseCheck +{ + bool&value; +public: + RecurseCheck(bool&aValue):value(aValue){ value=true;} + ~RecurseCheck(){value = false;} +}; + +Createrepo_impl::Createrepo_impl(bool enable_compat13, bool enable_compat14, QWidget *parent, const char *name) + :CreateRepo_Dlg(parent, name) +{ + inChangeCompat=true; + m_DisableFsync->setEnabled(false); + m_LogKeep->setEnabled(false); + if (!enable_compat13){ + m_svn13compat->setEnabled(false); + m_svn13compat->hide(); + } else { + m_svn13compat->setEnabled(true); + } + if (!enable_compat14){ + m_svn14compat->setEnabled(false); + m_svn14compat->hide(); + } else { + m_svn14compat->setEnabled(true); + } + inChangeCompat=false; +} + +void Createrepo_impl::fsTypeChanged(int which) +{ + m_DisableFsync->setEnabled(which==1); + m_LogKeep->setEnabled(which==1); +} + +QString Createrepo_impl::targetDir() +{ + KURL u = m_ReposPathinput->url(); + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + +QString Createrepo_impl::fsType() +{ + return m_FilesystemSelector->currentText(); +} + +bool Createrepo_impl::disableFsync() +{ + return m_DisableFsync->isChecked(); +} + +bool Createrepo_impl::keepLogs() +{ + return m_LogKeep->isChecked(); +} + +bool Createrepo_impl::createMain() +{ + return m_CreateMainDirs->isChecked(); +} + +bool Createrepo_impl::compat13()const +{ + return (m_svn13compat->isChecked()||!m_svn13compat->isEnabled()); +} + +bool Createrepo_impl::compat14()const +{ + return (m_svn14compat->isChecked()||!m_svn14compat->isEnabled()); +} + +void Createrepo_impl::compatChanged14(bool) +{ + if (inChangeCompat) { + return; + } + RecurseCheck rc(inChangeCompat); + if (m_svn14compat->isChecked()) { + m_svn13compat->setChecked(false); + } +} + +void Createrepo_impl::compatChanged13(bool) +{ + if (inChangeCompat) { + return; + } + RecurseCheck rc(inChangeCompat); + if (m_svn13compat->isChecked() && m_svn14compat->isEnabled()) { + m_svn14compat->setChecked(false); + } +} + +#include "createrepo_impl.moc" diff --git a/src/svnfrontend/createrepo_impl.h b/src/svnfrontend/createrepo_impl.h new file mode 100644 index 0000000..14f2743 --- /dev/null +++ b/src/svnfrontend/createrepo_impl.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CREATEREPO_IMPL_H +#define CREATEREPO_IMPL_H + +#include "createrepo_dlg.h" + +class Createrepo_impl: public CreateRepo_Dlg { + Q_OBJECT +public: + Createrepo_impl(bool enable_compat13,bool enable_compat14, QWidget *parent = 0, const char *name = 0); + QString targetDir(); + QString fsType(); + bool disableFsync(); + bool keepLogs(); + bool createMain(); + bool compat13()const; + bool compat14()const; + +protected slots: + virtual void fsTypeChanged(int); + virtual void compatChanged14(bool); + virtual void compatChanged13(bool); + +protected: + bool inChangeCompat; +}; + +#endif diff --git a/src/svnfrontend/dummydisplay.cpp b/src/svnfrontend/dummydisplay.cpp new file mode 100644 index 0000000..75037e2 --- /dev/null +++ b/src/svnfrontend/dummydisplay.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "dummydisplay.h" + +DummyDisplay::DummyDisplay() + : ItemDisplay() +{ +} + + +DummyDisplay::~DummyDisplay() +{ +} + +QWidget*DummyDisplay::realWidget() +{ + return 0L; +} + +SvnItem*DummyDisplay::Selected() +{ + return 0L; +} + +void DummyDisplay::SelectionList(QPtrList<SvnItem>*) +{ +} + +bool DummyDisplay::openURL( const KURL &,bool) +{ + return false; +} + +SvnItem*DummyDisplay::SelectedOrMain() +{ + return 0; +} + diff --git a/src/svnfrontend/dummydisplay.h b/src/svnfrontend/dummydisplay.h new file mode 100644 index 0000000..255a35c --- /dev/null +++ b/src/svnfrontend/dummydisplay.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DUMMYDISPLAY_H +#define DUMMYDISPLAY_H + +#include "itemdisplay.h" + +/** +@author Rajko Albrecht +*/ +class DummyDisplay : public ItemDisplay +{ +public: + DummyDisplay(); + virtual ~DummyDisplay(); + virtual QWidget*realWidget(); + virtual SvnItem*Selected(); + virtual void SelectionList(QPtrList<SvnItem>*); + virtual bool openURL( const KURL &url,bool noReinit=false ); + virtual SvnItem*SelectedOrMain(); +}; + +#endif diff --git a/src/svnfrontend/dumprepo_dlg.ui b/src/svnfrontend/dumprepo_dlg.ui new file mode 100644 index 0000000..8799419 --- /dev/null +++ b/src/svnfrontend/dumprepo_dlg.ui @@ -0,0 +1,200 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DumpRepoDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DumpRepoDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>291</width> + <height>218</height> + </rect> + </property> + <property name="caption"> + <string>Dump repo</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_ReposPath</cstring> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_RepoLabel</cstring> + </property> + <property name="text"> + <string>Repository to dump:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_OutfileLabel</cstring> + </property> + <property name="text"> + <string>Dump into:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>m_OutputFile</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_incrementalDump</cstring> + </property> + <property name="text"> + <string>incremental Dump</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_UseDeltas</cstring> + </property> + <property name="text"> + <string>Use deltas</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_Rangeonly</cstring> + </property> + <property name="text"> + <string>Dump revision range</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </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="text"> + <string>End revision:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Start revision:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>m_EndNumber</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="value"> + <number>-1</number> + </property> + <property name="minValue"> + <number>-1</number> + </property> + <property name="toolTip" stdset="0"> + <string>-1 for Head</string> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>m_StartNumber</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="value"> + <number>-1</number> + </property> + <property name="minValue"> + <number>-1</number> + </property> + <property name="toolTip" stdset="0"> + <string>-1 for Start</string> + </property> + </widget> + </grid> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_Rangeonly</sender> + <signal>toggled(bool)</signal> + <receiver>DumpRepoDlg</receiver> + <slot>slotDumpRange(bool)</slot> + </connection> +</connections> +<slots> + <slot access="protected">slotDumpRange(bool)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/dumprepo_impl.cpp b/src/svnfrontend/dumprepo_impl.cpp new file mode 100644 index 0000000..dfaeb69 --- /dev/null +++ b/src/svnfrontend/dumprepo_impl.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "dumprepo_impl.h" + +#include <kdebug.h> +#include <kurl.h> +#include <kurlrequester.h> +#include <kcombobox.h> +#include <knuminput.h> + +#include <qcheckbox.h> + +DumpRepo_impl::DumpRepo_impl(QWidget *parent, const char *name) + :DumpRepoDlg(parent, name) +{ +} + +void DumpRepo_impl::slotDumpRange(bool how) +{ + m_StartNumber->setEnabled(how); + m_EndNumber->setEnabled(how); +} + + +/*! + \fn DumpRepo_impl::reposPath() + */ +QString DumpRepo_impl::reposPath() +{ + KURL u = m_ReposPath->url(); + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + + +/*! + \fn DumpRepo_impl::targetFile() + */ +QString DumpRepo_impl::targetFile() +{ + KURL u = m_OutputFile->url(); + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + + +/*! + \fn DumpRepo_impl::incremental() + */ +bool DumpRepo_impl::incremental() +{ + return m_incrementalDump->isChecked(); +} + + +/*! + \fn DumpRepo_impl::use_dumps() + */ +bool DumpRepo_impl::use_deltas() +{ + return m_UseDeltas->isChecked(); +} + + +/*! + \fn DumpRepo_impl::useNumbers() + */ +bool DumpRepo_impl::useNumbers() +{ + return m_Rangeonly->isChecked(); +} + +/*! + \fn DumpRepo_impl::startNumber() + */ +int DumpRepo_impl::startNumber() +{ + return useNumbers()?m_StartNumber->value():-1; +} + +/*! + \fn DumpRepo_impl::endNumber() + */ +int DumpRepo_impl::endNumber() +{ + return useNumbers()?m_EndNumber->value():-1; +} + +#include "dumprepo_impl.moc" diff --git a/src/svnfrontend/dumprepo_impl.h b/src/svnfrontend/dumprepo_impl.h new file mode 100644 index 0000000..6e58256 --- /dev/null +++ b/src/svnfrontend/dumprepo_impl.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef DUMPREPO_IMPL_H +#define DUMPREPO_IMPL_H + +#include "dumprepo_dlg.h" + +class DumpRepo_impl: public DumpRepoDlg { +Q_OBJECT +public: + DumpRepo_impl(QWidget *parent = 0, const char *name = 0); + QString reposPath(); + QString targetFile(); + bool incremental(); + bool use_deltas(); + bool useNumbers(); + int startNumber(); + int endNumber(); +protected slots: + virtual void slotDumpRange(bool); +}; + +#endif diff --git a/src/svnfrontend/editproperty_impl.cpp b/src/svnfrontend/editproperty_impl.cpp new file mode 100644 index 0000000..eef6218 --- /dev/null +++ b/src/svnfrontend/editproperty_impl.cpp @@ -0,0 +1,209 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include <qstringlist.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +#include <ktextedit.h> +#include <kcombobox.h> +#include <kglobalsettings.h> +#include <kdebug.h> +#include <klocale.h> + +#include "editproperty_impl.h" + + +EditProperty_impl::EditProperty_impl(QWidget *parent, const char *name) + :EditPropsDlgData(parent, name) +{ + /// @TODO Read these values from a text or config file + fileProperties += ("svn:eol-style"); + fileProperties += ("svn:executable"); + fileProperties += ("svn:keywords"); + fileProperties += ("svn:needs-lock"); + fileProperties += ("svn:mime-type"); + + fileComments += i18n("One of <b>'native'</b>, <b>'LF'</b>, <b>'CR'</b>, <b>'CRLF'</b></b>."); + fileComments += i18n("If present, make the file executable.<br>" + "This property can not be set on a directory. " + "A non-recursive attempt will fail, and a recursive attempt " + "will set the property only on the file children of the folder."); + fileComments += i18n("Keywords to be expanded into the contents of a file.<br>" + "They can be inserted into documents by placing a keyword anchor " + "which is formatted as $KeywordName$.<br>" + "Valid keywords are:<br>" + "<b>URL/HeadURL</b> The URL for the head revision of the project.<br>" + "<b>Author/LastChangedBy</b> The last person to change the file.<br>" + "<b>Date/LastChangedDate</b> The date/time the object was last modified.<br>" + "<b>Revision/Rev/LastChangedRevision</b> The last revision the object changed.<br>" + "<b>Id</b> A compressed summary of the previous 4 keywords."); + fileComments += i18n("Set this to any value (e.g. <b>'*'</b>) to enforce locking for this file.<br>" + "The file will be set read-only when checked out or updated, " + "indicating that a user must acquire a lock on the file before " + "they can edit and commit changes."); + fileComments += i18n("The mimetype of the file. Used to determine " + "whether to merge the file and how to serve it from " + "Apache. A mimetype beginning with <b>'text/'</b> (or an absent " + "mimetype) is treated as text. Anything else is treated as binary."); + + dirProperties += ("svn:eol-style"); + dirProperties += ("svn:executable"); + dirProperties += ("svn:externals"); + dirProperties += ("svn:ignore"); + dirProperties += ("svn:mime-type"); + dirProperties += ("bugtraq:label"); + dirProperties += ("bugtraq:url"); + dirProperties += ("bugtraq:message"); + dirProperties += ("bugtraq:warnifnoissue"); + dirProperties += ("bugtraq:number"); + dirProperties += ("bugtraq:append"); + dirProperties += ("bugtraq:logregex"); + + dirComments += i18n("One of <b>'native'</b>, <b>'LF'</b>, <b>'CR'</b>, <b>'CRLF'</b></b>."); + dirComments += i18n("If present, make the file executable.<br>" + "This property can not be set on a directory. " + "A non-recursive attempt will fail, and a recursive attempt " + "will set the property only on the file children of the folder."); + /* TRANSLATORS: Do not translate "example" in the URL because this is according + TRANSLATORS: to http://www.rfc-editor.org/rfc/rfc2606.txt a reserved URL.*/ + dirComments += i18n("A newline separated list of module specifiers, each " + "consisting of a relative directory path, optional revision " + "flags, and a URL. For example:<br>" + "<nobr><b>foo http://example.com/repos/projectA</b></nobr><br>" + "<nobr><b>foo/bar -r 1234 http://example.com/repos/projectB</b></nobr>"); + dirComments += i18n("A newline separated list of file patterns to ignore."); + dirComments += i18n("The mimetype of the file. Used to determine " + "whether to merge the file and how to serve it from " + "Apache. A mimetype beginning with <b>'text/'</b> (or an absent " + "mimetype) is treated as text. Anything else is treated as binary."); + dirComments += i18n("Label text to show for the edit box where the user enters the issue number."); + /* TRANSLATORS: Do not translate "example" in the URL because this is according + TRANSLATORS: to http://www.rfc-editor.org/rfc/rfc2606.txt a reserved URL.*/ + dirComments += i18n("URL pointing to the issue tracker. It must contain " + "<b>%BUGID%</b> which gets replaced with the bug issue number. Example:<br>" + "<nobr><b>http://example.com/mantis/view.php?id=%BUGID%</b></nobr>"); + dirComments += i18n("String which is appended to a log message when an issue " + "number is entered. The string must contain <b>%BUGID%</b> " + "which gets replaced with the bug issue number."); + dirComments += i18n("Set to <b>'yes'</b> if a warning shall be shown when " + "no issue is entered in the commit dialog. Possible values:<br>" + "<b>'true'</b>/<b>'yes'</b> or <b>'false'</b>/<b>'no'</b>."); + dirComments += i18n("Set to <b>'false'</b> if your bugtracking system has " + "issues which are referenced not by numbers.<br>" + "Possible values: <b>'true'</b> or <b>'false'</b>."); + dirComments += i18n("Set to <b>'false'</b> if you want the bugtracking ID " + "to be inserted at the top of the log message. The " + "default is <b>'true'</b> which means the bugtracking " + "ID is appended to the log message."); + dirComments += i18n("Two regular expressions separated by a newline.<br>" + "The first expression is used to find a string referring to an issue, the " + "second expression is used to extract the bare bug ID from that string."); + + m_NameEdit->setAutoCompletion(true); + m_NameEdit->setCompletionMode(KGlobalSettings::CompletionPopupAuto); + m_NameEdit->setDuplicatesEnabled(false); + m_NameEdit->setHistoryItems(fileProperties, true); + isDir = false; + + QToolTip::add(m_NameEdit, "Select or enter new property"); + connect(m_NameEdit, SIGNAL(activated(const QString &)), this, SLOT(updateToolTip(const QString &))); +} + + +EditProperty_impl::~EditProperty_impl() { + kdDebug() << "EditProperty_impl got destroyed" << endl; +} + + +void EditProperty_impl::updateToolTip(const QString & selection) +{ + int i; + + if (isDir) { + i = dirProperties.findIndex(selection); + if (i >= 0) { + comment = dirComments[i]; + } else { + comment = "No help for this property available"; + } + } else { + i = fileProperties.findIndex(selection); + if (i >= 0) { + comment = fileComments[i]; + } else { + comment = "No help for this property available"; + } + } + + QToolTip::add(m_NameEdit, comment); +} + +void EditProperty_impl::setDir(bool dir) +{ + if (dir == isDir) { + // Change not necessary + return; + } + if (dir) { + m_NameEdit->clearHistory(); + m_NameEdit->setHistoryItems(dirProperties, true); + } else { + m_NameEdit->clearHistory(); + m_NameEdit->setHistoryItems(fileProperties, true); + } + + isDir = dir; +} + + +QString EditProperty_impl::propName()const +{ + return m_NameEdit->currentText(); +} + + +QString EditProperty_impl::propValue()const +{ + return m_ValueEdit->text(); +} + +void EditProperty_impl::setPropName(const QString&n) +{ + m_NameEdit->addToHistory(n); + m_NameEdit->setCurrentItem(n); + updateToolTip(n); +} + + +void EditProperty_impl::setPropValue(const QString&v) +{ + m_ValueEdit->setText(v); +} + +void EditProperty_impl::showHelp() +{ + QPoint pos = m_ValueEdit->pos(); + pos.setX(pos.x() + m_ValueEdit->width()/2); + pos.setY(pos.y() + m_ValueEdit->height()/4); + QWhatsThis::display(comment, mapToGlobal(pos)); +} + + +#include "editproperty_impl.moc" diff --git a/src/svnfrontend/editproperty_impl.h b/src/svnfrontend/editproperty_impl.h new file mode 100644 index 0000000..89fce30 --- /dev/null +++ b/src/svnfrontend/editproperty_impl.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef EDITPROPERTY_IMPL_H +#define EDITPROPERTY_IMPL_H + +#include "editpropsdlg.h" + +class QStringList; +class QString; + +class EditProperty_impl: public EditPropsDlgData { +Q_OBJECT +public: + EditProperty_impl(QWidget *parent = 0, const char *name = 0); + ~EditProperty_impl(); + + QString propName()const; + QString propValue()const; + void setPropName(const QString&); + void setPropValue(const QString&); + void setDir(bool dir); + +protected slots: + void updateToolTip(const QString&); + +private: + QStringList fileProperties; + QStringList fileComments; + QStringList dirProperties; + QStringList dirComments; + QString comment; + bool isDir; +protected slots: + virtual void showHelp(); +}; + +#endif diff --git a/src/svnfrontend/editpropsdlg.ui b/src/svnfrontend/editpropsdlg.ui new file mode 100644 index 0000000..460a468 --- /dev/null +++ b/src/svnfrontend/editpropsdlg.ui @@ -0,0 +1,244 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>EditPropsDlgData</class> +<widget class="QDialog"> + <property name="name"> + <cstring>EditPropsDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>412</width> + <height>303</height> + </rect> + </property> + <property name="caption"> + <string>Edit property</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>m_ButtonSpacer</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>107</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>OK</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>Cancel</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout24</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KHistoryCombo" row="0" column="1"> + <property name="name"> + <cstring>m_NameEdit</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_NameLabel</cstring> + </property> + <property name="text"> + <string>Property name:</string> + </property> + </widget> + <widget class="KTextEdit" row="1" column="1"> + <property name="name"> + <cstring>m_ValueEdit</cstring> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout23</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <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>60</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>m_ValueLabel</cstring> + </property> + <property name="text"> + <string>Property value:</string> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frame5</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="0" column="0"> + <property name="name"> + <cstring>helpButton</cstring> + </property> + <property name="maximumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Click for short info about pre-defined property name</string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>50</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1554">89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000005d9494441545885c5975d6c1cd515c77f333bfbbd138fede038a4756ca44204345963d1404bab587210a00a900a42e2818d14c1032f11cf08d9ea4b5f1378e425235e504555b58456446d6d1582122a9385046a881c6f62e28fdd35bbf6eeceecc7ecbd7d98ddf5ae67cdbabc70a4b39ab9f79cfbffdf73cf9c73579152f2638a06904824f6ec70e327e628302a25279a63428210cc09483db89648ed752dd3345d02bd6471c4348053400241bc3d680d70044c035c1f369342624ac1f9639944bed7da3d092c8e9833c019c05015888621e887a37717888683004851e1939b3a56194a15e2951a7160faea7ef3dc783631f383082c1d360d219905e29a0ab1303c75ac467c4c65fc1e1fa0b75907780d58ce0a3e5f127c746d934b4b838670989e1f349f01262736ba47a32b81a5c366bc016ee82198bcbfcab3c73506743f00d92dc1d28a45d51108a9b4fc1eba5767f2a8cae4d1413efccce12f57ca7cb5168b0bc1d215c39c3c9e4f247b1268dbb971cf7e9bdf3dea273e16006065c3616dc306e0f1097da72b17e70b00dc37a2f3d8fd1a3fbb3bc27b73ebfcf5fa010398bddc678e3db2d919090f8126b81185d353410ef4abd83548e7aa944a364ffea2af5bd03a485d9c2f307250675f54e5c59343d4659a0bd7870c6016186ff751db5f1a0917d743f0c2230ed1904ad1865c41f404df49e4f66a81a20d4e5de1e4c3fb39326c2124f14ff699335d09343eb533aa020f8f55191dd6b06b60d760f14ec903be9a834b0bf0d1025cbe01857227895fff5c6ff947c32a4f1f0fe0f781909cf958378d6e11380518fb2270744ca360d3d2e1fe8e406157e16a0a361bf3df15e19fc92aa5b2d3b20907a052dd5ee3e080c6433f2d00184272aa1b8184aac0f8480d50b1cab434e8ef24f0e5321df356d98dc0f2badd61e7d7dcb9a5b53affb9e1a0c702682a0841abf46ad028af827838047d319552a5339c5628d07aae38f0cd2ad49c4e9bcd8d0c474e1cea18fbd7e735521905cb69e6bac6400c5672c4e722e628906ace8c4ae9862de0f312584cfbf8db551888c18d15ef793bd63acffccae818fbefb782af56fdec945818c881946c136836969056a752f751a97bfcf872d93b06a055d779e5b7834443db5fb45591bc7db106043df6413f4809c2c59c6b79090946a44ea9e2eb8ed44502955bbcfadc210ff81ffe546539ef050737ca42827b0d50dc1c108dee268442d1eeeae711594ef3fb97ba832fac75076ff9b6b5539780705f729686cf7b6c1e51903c7144748067b6246f5da8f1cd7a1055d9dd77677e35579813305d130a95daf733777bbfc27d23918eb9373fa873331b40eb7182951a2005c01cf81a118014b805c6a9834fdd0e91944aeb884069fd2a6cdbdcce4a96321adfb3f196e48b80eb9b8246217a702d911292e49605aae2823615dcb19d9a2d6e6f75fea6d2d5a69ba6b700484e554fa7a0ad1b4a815911c4adb28311eb7d53fbe3a731560a502abb3d21b087cbdd6acec1710b98d91c6b773b0f4c2f6fa8c681fede8b59c5ef30027e42d261b84f2767f566f0f58a02c87c030b68eb05c73289bc909c2b5555729b45c20176559f28f0c6f37e1e9fd079fa97fdbcfe9c8611dddd3e1c80b56c01bb2201716eaa7a3aef2100d0b84026bfb813a35ccae1d7e8ae8ac3e183db37a27000468776b1d5602bbfc1e5c530209253d59767da313bdb9c2b934290ffc7423fd56286a01f8f862361ecea8e23297bed827eb0b6d27c70ad0f10796072279887c0c446222f24935292bf70fd2eb2e9b4279c7a2cc4bb97dcae782b037ffe14ca8e37ecabababbc373fd0029faabeecb91977cd9ce3f944f2729f392624b31f2e0cc5f7dfb638f94091c1c1a196cd96057fff6cdba7ad28924ddfe1fd2ffac814ef02447237f05d0900346eafe31febe64cba1439f3ce958871482f3031b2c9507f9050304434e6e641a954c0b66dd6b265aedc3258d93a00907713aef3ccf74ca0298f151233ff8e99678153cb9b7a62f99a1e6fb453a0d958622023342a5c1230419cdf6dd7ff170180df141379e02c7076366c8e02a3c08956576bd57652cd0ab757517eecbfe7ff039293b2bac36c6dc40000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>EditPropsDlg</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>EditPropsDlg</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>helpButton</sender> + <signal>clicked()</signal> + <receiver>EditPropsDlg</receiver> + <slot>showHelp()</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_ValueEdit</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonCancel</tabstop> +</tabstops> +<slots> + <slot access="protected">nameChanged(const QString&)</slot> + <slot access="protected">valueChanged()</slot> + <slot access="protected">showHelp()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>ktextedit.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/filelistviewitem.cpp b/src/svnfrontend/filelistviewitem.cpp new file mode 100644 index 0000000..19af4fe --- /dev/null +++ b/src/svnfrontend/filelistviewitem.cpp @@ -0,0 +1,322 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "filelistviewitem.h" +#include "kdesvnfilelist.h" +#include "src/settings/kdesvnsettings.h" +#include "helpers/sub2qt.h" +#include "src/svnqt/status.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/exception.hpp" +#include "src/svnqt/url.hpp" +#include "fronthelpers/widgetblockstack.h" + +#include <klocale.h> +#include <kiconloader.h> +#include <kfileitem.h> +#include <kdebug.h> +#include <kconfig.h> + +#include <qfileinfo.h> +#include <qpainter.h> + +const int FileListViewItem::COL_ICON = 0; +const int FileListViewItem::COL_NAME = 0; +const int FileListViewItem::COL_STATUS = 1; +const int FileListViewItem::COL_LAST_REV = 2; +const int FileListViewItem::COL_LAST_AUTHOR = 3; +const int FileListViewItem::COL_LAST_DATE = 4; +const int FileListViewItem::COL_IS_LOCKED = 5; + +//const int FileListViewItem::COL_CURRENT_REV = 5; + +FileListViewItem::FileListViewItem(kdesvnfilelist*_parent,const svn::StatusPtr&_stat) + : KListViewItem(_parent),SvnItem(_stat), + sortChar(0), + m_Ksvnfilelist(_parent) +{ + m_SvnWrapper = _parent->m_SvnWrapper; + init(); +} + +FileListViewItem::FileListViewItem(kdesvnfilelist*_parent,FileListViewItem*_parentItem,const svn::StatusPtr&_stat) + : KListViewItem(_parentItem),SvnItem(_stat), + sortChar(0), + m_Ksvnfilelist(_parent) +{ + m_SvnWrapper = _parent->m_SvnWrapper; + init(); +} + +SvnActions*FileListViewItem::getWrapper()const +{ + return m_SvnWrapper; +} + +void FileListViewItem::init() +{ + setText(COL_NAME,shortName()); + sortChar = isDir()?1:3; + setExpandable(isDir()); + if (shortName()[0]=='.') --sortChar; + update(); +} + +void FileListViewItem::setOpen(bool o) +{ + if (o && childCount()==0) { + { + WidgetBlockStack a(m_Ksvnfilelist); + m_Ksvnfilelist->slotItemRead(this); + } + m_Ksvnfilelist->setFocus(); + } + KListViewItem::setOpen(o); +} + +void FileListViewItem::setOpenNoBlock(bool o) +{ + if (o && childCount()==0) { + { + m_Ksvnfilelist->slotItemRead(this); + } + } + KListViewItem::setOpen(o); +} + +FileListViewItem::~FileListViewItem() +{ + if (isSelected()) { + /* + when item is selected and deleted signal selectionChanged isn't emitted + in QListView anymore and let kdesvn crash. + */ + setSelected(false); + m_Ksvnfilelist->selectionChanged(); + } +} + +void FileListViewItem::setStat(const svn::StatusPtr&stat) +{ + SvnItem::setStat(stat); + init(); +} + +void FileListViewItem::refreshStatus(bool childs,QPtrList<SvnItem>*exclude,bool depsonly) +{ + FileListViewItem*it; + + if (!depsonly) { + if (!m_Ksvnfilelist->refreshItem(this)) { + return; + } + } + if (!isValid()) { + return; + } + it = static_cast<FileListViewItem*>(parent()); + if (!childs) { + if (it && (!exclude || exclude->find(it)==-1)) { + it->refreshStatus(false,exclude); + } + } else if (firstChild()){ + it = static_cast<FileListViewItem*>(firstChild()); + while (it) { + if (!exclude || exclude->find(it)==-1) { + it->refreshStatus(true,exclude); + } + it = static_cast<FileListViewItem*>(it->nextSibling()); + } + } + repaint(); +} + +void FileListViewItem::makePixmap() +{ + int size = Kdesvnsettings::listview_icon_size(); + bool overlay = Kdesvnsettings::display_overlays(); + QPixmap pm; + if (m_Pixmap.isNull()) { + pm = getPixmap(size,overlay); + } else { + pm = getPixmap(m_Pixmap,size,overlay); + } + setPixmap(COL_ICON,pm); +} + +void FileListViewItem::setPreviewPix(const QPixmap& pixmap) +{ + if (pixmap.isNull()) return; + m_Pixmap = pixmap; + int size = Kdesvnsettings::listview_icon_size(); + bool overlay = Kdesvnsettings::display_overlays(); + QPixmap pm = getPixmap(pixmap,size,overlay); + setPixmap(COL_ICON,pm); +} + +bool FileListViewItem::isParent(QListViewItem*which) +{ + if (!which) return false; + QListViewItem*item = this; + while ( (item=item->parent())) { + if (item==which) { + return true; + } + } + return false; +} + +void FileListViewItem::update() +{ + makePixmap(); + if (!isVersioned()) { + setText(COL_STATUS,i18n("Not versioned")); + return; + } + setText(COL_STATUS,infoText()); + setText(COL_LAST_AUTHOR,cmtAuthor()); + setText(COL_LAST_DATE,KGlobal::locale()->formatDateTime(fullDate())); + setText(COL_LAST_REV,QString("%1").arg(cmtRev())); + setText(COL_IS_LOCKED,lockOwner()); +} + +int FileListViewItem::compare( QListViewItem* item, int col, bool ascending ) const +{ + FileListViewItem* k = static_cast<FileListViewItem*>( item ); + if ( sortChar != k->sortChar ) { + // Dirs are always first, even when sorting in descending order + return !ascending ? k->sortChar - sortChar : sortChar - k->sortChar; + } + if (col==COL_LAST_DATE) { + return fullDate().secsTo(k->fullDate()); + } + if (col==COL_LAST_REV) { + return k->cmtRev()-cmtRev(); + } + + if (Kdesvnsettings::case_sensitive_sort()) { + if (Kdesvnsettings::locale_is_casesensitive()) { + return text(col).localeAwareCompare(k->text(col)); + } + return text(col).compare(k->text(col)); + } else { + return text(col).lower().localeAwareCompare(k->text(col).lower()); + } +} + +void FileListViewItem::removeChilds() +{ + QListViewItem*temp; + while ((temp=firstChild())) { + delete temp; + } +} + +void FileListViewItem::updateStatus(const svn::StatusPtr&s) +{ + setStat(s); +} + +SvnItem* FileListViewItem::getParentItem()const +{ + return static_cast<FileListViewItem*>(parent()); +} +/*! + \fn FileListViewItem::getParentDir()const + */ + QString FileListViewItem::getParentDir()const +{ + SvnItem*temp = getParentItem(); + if (!temp) return QString::null; + return temp->fullName(); +} + +void FileListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + bool colors = Kdesvnsettings::colored_state(); + if (!colors||m_bgColor==NONE) { + KListViewItem::paintCell(p,cg,column,width,alignment); + return; + } + QColorGroup _cg = cg; + QColor _bgColor; + switch(m_bgColor) { + case UPDATES: + _bgColor = Kdesvnsettings::color_need_update(); + break; + case LOCKED: + _bgColor = Kdesvnsettings::color_locked_item(); + break; + case ADDED: + _bgColor = Kdesvnsettings::color_item_added(); + break; + case DELETED: + _bgColor = Kdesvnsettings::color_item_deleted(); + break; + case MODIFIED: + _bgColor = Kdesvnsettings::color_changed_item(); + break; + case MISSING: + _bgColor = Kdesvnsettings::color_missed_item(); + break; + case NOTVERSIONED: + _bgColor = Kdesvnsettings::color_notversioned_item(); + break; + case CONFLICT: + _bgColor = Kdesvnsettings::color_conflicted_item(); + break; + case NEEDLOCK: + _bgColor = Kdesvnsettings::color_need_lock(); + break; + default: + KListViewItem::paintCell(p,cg,column,width,alignment); + return; + break; + } + const QPixmap *pm = listView()->viewport()->backgroundPixmap(); + if (pm && !pm->isNull()) { + _cg.setBrush(QColorGroup::Base, QBrush(_bgColor, *pm)); + QPoint o = p->brushOrigin(); + p->setBrushOrigin( o.x()-listView()->contentsX(), o.y()-listView()->contentsY() ); + } else { + if (listView()->viewport()->backgroundMode()==Qt::FixedColor) { + _cg.setColor(QColorGroup::Background,_bgColor); + } else { + _cg.setColor(QColorGroup::Base,_bgColor); + } + } + QListViewItem::paintCell(p, _cg, column, width, alignment); +} + +const svn::Revision&FileListViewItem::correctPeg()const +{ + return m_Ksvnfilelist->remoteRevision(); +} + +FileListViewItem*FileListViewItem::findChild(const QString&aName) +{ + FileListViewItem*_item = (FileListViewItem*)firstChild(); + while (_item) { + if (_item->fullName()==aName) { + return _item; + } + _item = (FileListViewItem*)_item->nextSibling(); + } + return 0L; +} diff --git a/src/svnfrontend/filelistviewitem.h b/src/svnfrontend/filelistviewitem.h new file mode 100644 index 0000000..e8f0d64 --- /dev/null +++ b/src/svnfrontend/filelistviewitem.h @@ -0,0 +1,88 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef FILELISTVIEWITEM_H +#define FILELISTVIEWITEM_H + +#include "svnitem.h" +#include <klistview.h> +#include <qdatetime.h> +#include <qptrlist.h> +#include "src/svnqt/svnqttypes.hpp" + +class QPainter; +class KFileItem; +class kdesvnfilelist; +class SvnActions; + +/** +@author Rajko Albrecht +*/ +class FileListViewItem : public KListViewItem,public SvnItem +{ + friend class kdesvnfilelist; +public: + FileListViewItem(kdesvnfilelist*,const svn::StatusPtr&); + FileListViewItem(kdesvnfilelist*,FileListViewItem*,const svn::StatusPtr&); + + virtual ~FileListViewItem(); + virtual int compare( QListViewItem* i, int col, bool ascending ) const; + + virtual void updateStatus(const svn::StatusPtr&s); + virtual void refreshStatus(bool childs=false,QPtrList<SvnItem> *exclude = 0,bool depsonly=false); + +#if 0 + virtual void refreshMe(); +#endif + + void removeChilds(); + bool isParent(QListViewItem*which); + + static const int COL_ICON,COL_NAME,COL_LAST_REV,COL_LAST_AUTHOR,COL_LAST_DATE,COL_STATUS/*,COL_CURRENT_REV*/,COL_IS_LOCKED; + + virtual QString getParentDir()const; + virtual SvnItem* getParentItem()const; + virtual FileListViewItem*fItem(){return this;} + virtual void setStat(const svn::StatusPtr&); + virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + virtual void setOpen(bool o); + virtual void setOpenNoBlock(bool o); + + virtual void setPreviewPix(const QPixmap& pixmap); + virtual const svn::Revision&correctPeg()const; + virtual FileListViewItem*findChild(const QString&); + +protected: + QColor m_highColor; + short int sortChar; + kdesvnfilelist*m_Ksvnfilelist; + + virtual void update(); + + void makePixmap(); + void init(); + virtual SvnActions*getWrapper()const; + SvnActions*m_SvnWrapper; + QPixmap m_Pixmap; +}; + +typedef QPtrList<FileListViewItem> FileListViewItemList; +typedef QPtrListIterator<FileListViewItem> FileListViewItemListIterator; + +#endif diff --git a/src/svnfrontend/fillcachethread.cpp b/src/svnfrontend/fillcachethread.cpp new file mode 100644 index 0000000..ddaa934 --- /dev/null +++ b/src/svnfrontend/fillcachethread.cpp @@ -0,0 +1,123 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "fillcachethread.h" +#include "tcontextlistener.h" + +#include "src/svnqt/cache/LogCache.hpp" +#include "src/svnqt/cache/ReposLog.hpp" +#include "src/svnqt/cache/DatabaseException.hpp" +#include "src/kdesvn_events.h" + +#include <qobject.h> +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> + +FillCacheThread::FillCacheThread(QObject*_parent,const QString&reposRoot) + : QThread(),mutex(),m_SvnContextListener(0) +{ + m_Parent = _parent; + m_CurrentContext = new svn::Context(); + + m_SvnContextListener = new ThreadContextListener(m_Parent); + QObject::connect(m_SvnContextListener,SIGNAL(sendNotify(const QString&)),m_Parent,SLOT(slotNotifyMessage(const QString&))); + + m_CurrentContext->setListener(m_SvnContextListener); + m_what = reposRoot; + m_Svnclient = svn::Client::getobject(m_CurrentContext,0); +} + +FillCacheThread::~FillCacheThread() +{ + m_CurrentContext->setListener(0); + delete m_Svnclient; + m_SvnContextListener=0; +} + +const QString&FillCacheThread::reposRoot()const +{ + return m_what; +} + +void FillCacheThread::cancelMe() +{ + // method is threadsafe! + m_SvnContextListener->setCanceled(true); +} + +void FillCacheThread::run() +{ + svn::Revision where = svn::Revision::HEAD; + QString ex; + svn::cache::ReposLog rl(m_Svnclient,m_what); + bool breakit=false; + KApplication*k = KApplication::kApplication(); + try { + svn::Revision latestCache = rl.latestCachedRev(); + svn::Revision Head = rl.latestHeadRev(); + Q_LLONG i = latestCache.revnum(); + if (i<0) { + i=0; + } + Q_LLONG j = Head.revnum(); + + Q_LLONG _max=j-i; + Q_LLONG _cur=0; + + FillCacheStatusEvent*fev; + if (k) { + fev = new FillCacheStatusEvent(_cur,_max); + k->postEvent(m_Parent,fev); + } + + if (i<j) { + for (;i<j;i+=200) { + _cur+=200; + rl.fillCache(i); + + if (m_SvnContextListener->contextCancel()) { + m_SvnContextListener->contextNotify(i18n("Filling cache canceled.")); + breakit=true; + break; + } + if (latestCache==rl.latestCachedRev()) { + break; + } + if (k) { + fev = new FillCacheStatusEvent(_cur>_max?_max:_cur,_max); + k->postEvent(m_Parent,fev); + } + latestCache=rl.latestCachedRev(); + } + if (latestCache.revnum()<Head.revnum()) { + rl.fillCache(Head.revnum()); + } + i=Head.revnum(); + m_SvnContextListener->contextNotify(i18n("Cache filled up to revision %1").arg(i)); + } + } catch (const svn::Exception&e) { + m_SvnContextListener->contextNotify(e.msg()); + } + if (k && !breakit) { + QCustomEvent*ev = new QCustomEvent(EVENT_LOGCACHE_FINISHED); + ev->setData((void*)this); + k->postEvent(m_Parent,ev); + } +} diff --git a/src/svnfrontend/fillcachethread.h b/src/svnfrontend/fillcachethread.h new file mode 100644 index 0000000..04b0ec2 --- /dev/null +++ b/src/svnfrontend/fillcachethread.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _FILLCACHE_THREAD_H +#define _FILLCACHE_THREAD_H + +#include "src/svnqt/client.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/status.hpp" +#include "ccontextlistener.h" +#include "eventnumbers.h" +#include "frontendtypes.h" + +#include <qthread.h> +#include <qevent.h> + +class QObject; + +class FillCacheThread:public QThread +{ +public: + FillCacheThread(QObject*,const QString&reposRoot); + virtual ~FillCacheThread(); + virtual void run(); + virtual void cancelMe(); + + const QString&reposRoot()const; + +protected: + QMutex mutex; + svn::Client* m_Svnclient; + svn::ContextP m_CurrentContext; + svn::smart_pointer<ThreadContextListener> m_SvnContextListener; + QObject*m_Parent; + QString m_what; +}; + +#endif diff --git a/src/svnfrontend/frontendtypes.h b/src/svnfrontend/frontendtypes.h new file mode 100644 index 0000000..0f45ecf --- /dev/null +++ b/src/svnfrontend/frontendtypes.h @@ -0,0 +1,11 @@ +#ifndef _FRONTEND_TYPES_H +#define _FRONTEND_TYPES_H + +#include "svnqt/shared_pointer.hpp" + +class ThreadContextListener; + +typedef svn::smart_pointer<ThreadContextListener> ThreadContextListenerP; + +#endif + diff --git a/src/svnfrontend/fronthelpers/checkoutinfo.ui b/src/svnfrontend/fronthelpers/checkoutinfo.ui new file mode 100644 index 0000000..a880bd3 --- /dev/null +++ b/src/svnfrontend/fronthelpers/checkoutinfo.ui @@ -0,0 +1,223 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CheckoutInfo</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CheckoutInfo</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>275</width> + <height>185</height> + </rect> + </property> + <property name="caption"> + <string>Checkout info</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_UrlEdit</cstring> + </property> + <property name="showLocalProtocol"> + <bool>true</bool> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_TargetLabel</cstring> + </property> + <property name="text"> + <string>Select target directory:</string> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>m_TargetSelector</cstring> + </property> + <property name="showLocalProtocol"> + <bool>true</bool> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_UrlLabel</cstring> + </property> + <property name="text"> + <string>Enter URL:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="Rangeinput_impl"> + <property name="name"> + <cstring>m_RangeInput</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_CreateDirButton</cstring> + </property> + <property name="text"> + <string>Append source url name to subfolder</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_overwriteButton</cstring> + </property> + <property name="text"> + <string>Overwrite existing</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>May existing unversioned items ovewritten</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_ignoreExternals</cstring> + </property> + <property name="text"> + <string>Ignore externals</string> + </property> + <property name="toolTip" stdset="0"> + <string>Ignore externals while operation</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="DepthSelector"> + <property name="name"> + <cstring>m_DepthSelector</cstring> + </property> + <property name="minimumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_ShowExplorer</cstring> + </property> + <property name="text"> + <string>Open after job</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>Rangeinput_impl</class> + <header location="local">rangeinput_impl.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <property type="Bool">StartOnly</property> + </customwidget> + <customwidget> + <class>DepthSelector</class> + <header location="local">src/ksvnwidgets/depthselector.h</header> + <sizehint> + <width>-1</width> + <height>30</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<slots> + <slot access="protected">urlChanged(const QString&)</slot> +</slots> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>rangeinput_impl.h</includehint> + <includehint>src/ksvnwidgets/depthselector.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/fronthelpers/checkoutinfo_impl.cpp b/src/svnfrontend/fronthelpers/checkoutinfo_impl.cpp new file mode 100644 index 0000000..8d207e7 --- /dev/null +++ b/src/svnfrontend/fronthelpers/checkoutinfo_impl.cpp @@ -0,0 +1,211 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "checkoutinfo_impl.h" +#include "rangeinput_impl.h" +#include "src/ksvnwidgets/depthselector.h" +#include "src/svnqt/url.hpp" +#include "helpers/ktranslateurl.h" +#include <kurlrequester.h> +#include <qlabel.h> +#include <qtooltip.h> + +#include <klineedit.h> +#include <qcheckbox.h> +#include <klocale.h> +#include <kdebug.h> + +CheckoutInfo_impl::CheckoutInfo_impl(QWidget *parent, const char *name) + :CheckoutInfo(parent, name) +{ + m_RangeInput->setStartOnly(true); + m_RangeInput->setHeadDefault(); +} + +CheckoutInfo_impl::~CheckoutInfo_impl() +{ +} + +svn::Revision CheckoutInfo_impl::toRevision() +{ + return m_RangeInput->getRange().first; +} + +QString CheckoutInfo_impl::reposURL() +{ + KURL uri(m_UrlEdit->url()); + QString proto = svn::Url::transformProtokoll(uri.protocol()); + if (proto=="file"&&!m_UrlEdit->url().startsWith("ksvn+file:")) { + uri.setProtocol(""); + } else { + uri.setProtocol(proto); + } + return uri.prettyURL(); +} + +QString CheckoutInfo_impl::targetDir() +{ + if (!m_CreateDirButton->isChecked()) { + return m_TargetSelector->url(); + } + QString _uri = reposURL(); + while (_uri.endsWith("/")) { + _uri.truncate(_uri.length()-1); + } + QStringList l = QStringList::split('/',_uri); + if (l.count()==0) { + return m_TargetSelector->url(); + } + return m_TargetSelector->url()+"/"+l[l.count()-1]; +} + +bool CheckoutInfo_impl::overwrite() +{ + return m_overwriteButton->isChecked(); +} + +/*! + \fn CheckoutInfo_impl::setTargetUrl(const QString&) + */ +void CheckoutInfo_impl::setTargetUrl(const QString&what) +{ + m_TargetSelector->setURL(what); +} + +void CheckoutInfo_impl::setStartUrl(const QString&what) +{ + KURL uri(what); + if (uri.protocol()=="file") { + if (what.startsWith("file:")) { + uri.setProtocol("ksvn+file"); + } else { + uri.setProtocol(""); + } + } else { + uri.setProtocol(helpers::KTranslateUrl::makeKdeUrl(uri.protocol())); + } + m_UrlEdit->setURL(uri.prettyURL()); +} + +void CheckoutInfo_impl::hideDepth(bool how,bool overwriteAsRecurse) +{ + if (how) { + m_DepthSelector->setEnabled(false); + m_DepthSelector->hide(); + if (overwriteAsRecurse) { + QToolTip::add( m_overwriteButton, i18n( "Make operation recursive." ) ); + m_overwriteButton->setText(i18n("Recursive")); + } + } else if (!how) { + m_DepthSelector->setEnabled(false); + m_DepthSelector->show(); + m_overwriteButton->setText( tr2i18n( "Overwrite existing" ) ); + QToolTip::add( m_overwriteButton, tr2i18n( "May existing unversioned items ovewritten" ) ); + } + adjustSize(); +} + +svn::Depth CheckoutInfo_impl::getDepth() +{ + if (m_DepthSelector->isEnabled()) { + return m_DepthSelector->getDepth(); + } + return svn::DepthUnknown; +} + +void CheckoutInfo_impl::disableTargetDir(bool how) +{ + if (how) { + m_TargetSelector->setEnabled(false); + m_TargetSelector->hide(); + m_TargetLabel->hide(); + } else if (!how) { + m_TargetSelector->setEnabled(true); + m_TargetSelector->show(); + m_TargetLabel->show(); + } +} + +void CheckoutInfo_impl::disableOpen(bool how) +{ + if (how) { + m_ShowExplorer->setEnabled(false); + m_ShowExplorer->hide(); + } else if (!how) { + m_ShowExplorer->setEnabled(true); + m_ShowExplorer->show(); + } +} + + +/*! + \fn CheckoutInfo_impl::openAfterJob() + */ +bool CheckoutInfo_impl::openAfterJob() +{ + return m_ShowExplorer->isChecked(); +} + +/*! + \fn CheckoutInfo_impl::disableRange(bool how) + */ +void CheckoutInfo_impl::disableRange(bool how) +{ + if (how) { + m_RangeInput->setEnabled(false); + m_RangeInput->hide(); + } else { + m_RangeInput->setEnabled(true); + m_RangeInput->show(); + } +} + +void CheckoutInfo_impl::urlChanged(const QString&) +{ +} + +void CheckoutInfo_impl::disableAppend(bool how) +{ + m_CreateDirButton->setChecked(!how); + if (how) { + m_CreateDirButton->hide(); + } else { + m_CreateDirButton->show(); + } +} + +/*! + \fn CheckoutInfo_impl::ignoreExternals() + */ +bool CheckoutInfo_impl::ignoreExternals() +{ + return m_ignoreExternals->isChecked(); +} + +void CheckoutInfo_impl::disableExternals(bool how) +{ + m_ignoreExternals->setChecked(!how); + if (how) { + m_ignoreExternals->hide(); + } else { + m_ignoreExternals->show(); + } +} + +#include "checkoutinfo_impl.moc" diff --git a/src/svnfrontend/fronthelpers/checkoutinfo_impl.h b/src/svnfrontend/fronthelpers/checkoutinfo_impl.h new file mode 100644 index 0000000..600e179 --- /dev/null +++ b/src/svnfrontend/fronthelpers/checkoutinfo_impl.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CHECKOUTINFO_IMPL_H +#define CHECKOUTINFO_IMPL_H + +#include "checkoutinfo.h" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/svnqttypes.hpp" +#include "kurl.h" + +class CheckoutInfo_impl: public CheckoutInfo { +Q_OBJECT +public: + CheckoutInfo_impl(QWidget *parent = 0, const char *name = 0); + virtual ~CheckoutInfo_impl(); + + svn::Revision toRevision(); + QString reposURL(); + QString targetDir(); + + bool overwrite(); + svn::Depth getDepth(); + void setStartUrl(const QString&); + + void disableForce(bool how); + void disableTargetDir(bool how); + void disableAppend(bool how); + void disableOpen(bool how); + void disableExternals(bool how); + bool openAfterJob(); + virtual void disableRange(bool how); + void setTargetUrl(const QString&); + bool ignoreExternals(); + void hideDepth(bool hide,bool overwriteAsRecurse); +protected slots: + virtual void urlChanged(const QString&); +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/cursorstack.h b/src/svnfrontend/fronthelpers/cursorstack.h new file mode 100644 index 0000000..471af6e --- /dev/null +++ b/src/svnfrontend/fronthelpers/cursorstack.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +/*! + * \file cursorstack.h + * \brief Defines and implements CursorStack + */ +#ifndef __CURSOR_STACK_H +#define __CURSOR_STACK_H + +#include <kapplication.h> +#include <qcursor.h> + +//! Change cursor on stack. +/*! May used in methods where more than returns exists. Cursor will restored on destruction + * of class instance. + */ +class CursorStack +{ +public: + //! Constructor. + /*! + * Create instance and changes the application cursor to \a c + * \param c cursortype to set. + */ + CursorStack(Qt::CursorShape c = Qt::WaitCursor) + { + KApplication::setOverrideCursor(QCursor(c)); + } + //! Destructor. + /*! + * Restores the application cursor to value before construction. + */ + ~CursorStack() + { + KApplication::restoreOverrideCursor(); + } +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/propertyitem.cpp b/src/svnfrontend/fronthelpers/propertyitem.cpp new file mode 100644 index 0000000..0e25d5f --- /dev/null +++ b/src/svnfrontend/fronthelpers/propertyitem.cpp @@ -0,0 +1,56 @@ +#include "propertyitem.h" +#include <klocale.h> +#include <kiconloader.h> + +PropertyListViewItem::PropertyListViewItem(KListView *parent,const QString&aName,const QString&aValue) + : KListViewItem(parent),m_currentName(aName),m_startName(aName),m_currentValue(aValue),m_startValue(aValue),m_deleted(false) +{ + setMultiLinesEnabled(true); + setText(0,startName()); + setText(1,startValue()); +} + +PropertyListViewItem::PropertyListViewItem(KListView *parent) + : KListViewItem(parent),m_currentName(""),m_startName(""),m_currentValue(""),m_startValue(""),m_deleted(false) +{ + setMultiLinesEnabled(true); + setText(0,startName()); + setText(1,startValue()); +} + +PropertyListViewItem::~PropertyListViewItem() +{ +} + +void PropertyListViewItem::checkValue() +{ + m_currentValue=text(1); +} + +void PropertyListViewItem::checkName() +{ + m_currentName=text(0); +} + +bool PropertyListViewItem::different()const +{ + return m_currentName!=m_startName || m_currentValue!=m_startValue || deleted(); +} + +void PropertyListViewItem::deleteIt() +{ + m_deleted = true; + setPixmap(0,KGlobal::iconLoader()->loadIcon("cancel",KIcon::Desktop,16)); +} + +void PropertyListViewItem::unDeleteIt() +{ + m_deleted = false; + setPixmap(0,QPixmap()); +} + +bool PropertyListViewItem::protected_Property(const QString&what) +{ + if (what.compare("svn:special")!=0) return false; + return true; +} diff --git a/src/svnfrontend/fronthelpers/propertyitem.h b/src/svnfrontend/fronthelpers/propertyitem.h new file mode 100644 index 0000000..c630c7c --- /dev/null +++ b/src/svnfrontend/fronthelpers/propertyitem.h @@ -0,0 +1,49 @@ +#ifndef _PROPERTYITEM_H +#define _PROPERTYITEM_H + +#include <klistview.h> + +class PropertiesDlg; +class Propertylist; + +class PropertyListViewItem:public KListViewItem +{ + friend class PropertiesDlg; + friend class Propertylist; + + public: + static const int _RTTI_ = 1001; + PropertyListViewItem(KListView *parent,const QString&,const QString&); + PropertyListViewItem(KListView *parent); + virtual ~PropertyListViewItem(); + + const QString&startName()const{return m_startName;} + const QString&startValue()const{return m_startValue;} + const QString¤tName()const{return m_currentName;} + const QString¤tValue()const{return m_currentValue;} + + void checkValue(); + void checkName(); + void deleteIt(); + void unDeleteIt(); + bool deleted()const{return m_deleted;} + + bool different()const; + + virtual int rtti()const{return _RTTI_;} + + //! Check if a specific property may just internale + /*! + * That means, a property of that may not edit,added or deleted. + * + * This moment it just checks for "svn:special" + * \return true if protected property otherwise false + */ + static bool protected_Property(const QString&); + + protected: + QString m_currentName,m_startName,m_currentValue,m_startValue; + bool m_deleted; +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/propertylist.cpp b/src/svnfrontend/fronthelpers/propertylist.cpp new file mode 100644 index 0000000..8fa3b66 --- /dev/null +++ b/src/svnfrontend/fronthelpers/propertylist.cpp @@ -0,0 +1,166 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "propertylist.h" +#include "src/svnfrontend/fronthelpers/propertyitem.h" + +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> + + +Propertylist::Propertylist(QWidget *parent, const char *name) + : KListView(parent, name),m_commitit(false) +{ + addColumn(i18n("Property")); + addColumn(i18n("Value")); + setShowSortIndicator(true); + setAllColumnsShowFocus (true); + setRootIsDecorated(false); + setSortColumn(0); + setAcceptDrops(false); + connect(this,SIGNAL(itemRenamed(QListViewItem*,const QString&,int)),this,SLOT(slotItemRenamed(QListViewItem*,const QString&,int))); + + connect(this,SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),this, + SLOT(slotContextMenuRequested(QListViewItem *, const QPoint &, int))); + //setFullWidth( TRUE ); +} + + +Propertylist::~Propertylist() +{ +} + +void Propertylist::displayList(const svn::PathPropertiesMapListPtr&propList,bool editable,const QString&aCur) +{ + viewport()->setUpdatesEnabled(false); + clear(); + setItemsRenameable(editable); + setRenameable(0,editable); + setRenameable(1,editable); + if (propList) { + m_current = aCur; + svn::PathPropertiesMapList::const_iterator lit; + svn::PropertiesMap pmap; + for (lit=propList->begin();lit!=propList->end();++lit) { + pmap = (*lit).second; + /* just want the first one */ + break; + } + svn::PropertiesMap::const_iterator pit; + for (pit=pmap.begin();pit!=pmap.end();++pit) { + PropertyListViewItem * ki = new PropertyListViewItem(this, + pit.key(), + pit.data()); + } + } + viewport()->setUpdatesEnabled(true); + viewport()->repaint(); +} + +void Propertylist::clear() +{ + KListView::clear(); +} + +/*! + \fn PropertiesDlg::slotItemRenamed(QListViewItem*item,const QString & str,int col ) + */ +void Propertylist::slotItemRenamed(QListViewItem*_item,const QString & text,int col ) +{ + if (!_item || _item->rtti()!=PropertyListViewItem::_RTTI_) return; + PropertyListViewItem*item = static_cast<PropertyListViewItem*> (_item); + + kdDebug()<<"Text: "<< text << " in col "<<col << endl; + + if (text.isEmpty()&&col == 0) { + // fresh added + if (item->currentName().isEmpty()) { + delete item; + } else { + item->setText(0,item->currentName()); + } + return; + } + if (PropertyListViewItem::protected_Property(item->text(0)) || + PropertyListViewItem::protected_Property(item->currentName())) { + KMessageBox::error(this,i18n("This property may not set by users.\nRejecting it."),i18n("Protected property")); + item->setText(0,item->currentName()); + item->setText(1,item->currentValue()); + return; + } + if (checkExisting(item->text(0),item)) { + KMessageBox::error(this,i18n("A property with that name exists.\nRejecting it."),i18n("Double property")); + item->setText(0,item->currentName()); + item->setText(1,item->currentValue()); + return; + } + + if (col==0) { + item->checkName(); + } else { + item->checkValue(); + } + if (commitchanges() && item->different()) { + svn::PropertiesMap pm; + QValueList<QString> dels; + pm[item->currentName()]=item->currentValue(); + if (item->currentName()!=item->startName()){ + dels.push_back(item->startName()); + } + emit sigSetProperty(pm,dels,m_current); + } +} + +bool Propertylist::checkExisting(const QString&aName,QListViewItem*it) +{ + if (!it) { + return findItem(aName,0)!=0; + } + QListViewItemIterator iter(this); + while ( iter.current() ) { + if ( iter.current()==it) { + ++iter; + continue; + } + if (iter.current()->text(0)==aName) { + return true; + } + ++iter; + } + return false; +} + +void Propertylist::addCallback(QObject*ob) +{ + if (ob) { + connect(this,SIGNAL(sigSetProperty(const svn::PropertiesMap&,const QValueList<QString>&,const QString&)), + ob,SLOT(slotChangeProperties(const svn::PropertiesMap&,const QValueList<QString>&,const QString&))); + } +} + +/*! + \fn Propertylist::slotContextMenuRequested(QListViewItem *, const QPoint &, int) + */ +void Propertylist::slotContextMenuRequested(QListViewItem *, const QPoint &, int) +{ + /// @todo implement me +} + +#include "propertylist.moc" diff --git a/src/svnfrontend/fronthelpers/propertylist.h b/src/svnfrontend/fronthelpers/propertylist.h new file mode 100644 index 0000000..d3cf245 --- /dev/null +++ b/src/svnfrontend/fronthelpers/propertylist.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef PROPERTYLIST_H +#define PROPERTYLIST_H + +#include <klistview.h> +#include "src/svnqt/svnqttypes.hpp" + +/** + @author +*/ +class Propertylist : public KListView +{ + Q_OBJECT +public: + Propertylist(QWidget *parent = 0, const char *name = 0); + ~Propertylist(); + + bool checkExisting(const QString&aName,QListViewItem*it=0); + bool commitchanges()const{return m_commitit;} + void setCommitchanges(bool how){m_commitit=how;} + void addCallback(QObject*); + +public slots: + virtual void displayList(const svn::PathPropertiesMapListPtr&,bool,const QString&); + virtual void clear(); + +protected slots: + virtual void slotItemRenamed(QListViewItem*item,const QString & str,int col ); + +signals: + void sigSetProperty(const svn::PropertiesMap&,const QValueList<QString>&,const QString&); +protected: + bool m_commitit; + QString m_current; +protected slots: + virtual void slotContextMenuRequested(QListViewItem *, const QPoint &, int); +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/rangeinput.ui b/src/svnfrontend/fronthelpers/rangeinput.ui new file mode 100644 index 0000000..18e8884 --- /dev/null +++ b/src/svnfrontend/fronthelpers/rangeinput.ui @@ -0,0 +1,285 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>RangeInputDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RangeInput</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>397</width> + <height>272</height> + </rect> + </property> + <property name="caption"> + <string>Revisions</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>m_startRevBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Start with revision</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntNumInput" row="0" column="2"> + <property name="name"> + <cstring>m_startRevInput</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_startNumberButton</cstring> + </property> + <property name="text"> + <string>N&umber</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>m_startDateButton</cstring> + </property> + <property name="text"> + <string>Date</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_startStartButton</cstring> + </property> + <property name="text"> + <string>S&TART</string> + </property> + </widget> + <widget class="KDateTimeWidget" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_startDateInput</cstring> + </property> + </widget> + <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_startHeadButton</cstring> + </property> + <property name="text"> + <string>HEAD</string> + </property> + </widget> + <widget class="QRadioButton" row="4" column="0"> + <property name="name"> + <cstring>m_startWorkingButton</cstring> + </property> + <property name="text"> + <string>WORKING</string> + </property> + <property name="toolTip" stdset="0"> + <string>Select current working copy changes</string> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>m_stopRevBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Stop with revision</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntNumInput" row="0" column="2"> + <property name="name"> + <cstring>m_endRevInput</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_stopNumberButton</cstring> + </property> + <property name="text"> + <string>Number</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="KDateTimeWidget" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_stopDateInput</cstring> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>m_stopDateButton</cstring> + </property> + <property name="text"> + <string>Date</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_stopStartButton</cstring> + </property> + <property name="text"> + <string>START</string> + </property> + </widget> + <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_stopHeadButton</cstring> + </property> + <property name="text"> + <string>HEAD</string> + </property> + </widget> + <widget class="QRadioButton" row="4" column="0"> + <property name="name"> + <cstring>m_stopWorkingButton</cstring> + </property> + <property name="text"> + <string>WORKING</string> + </property> + <property name="toolTip" stdset="0"> + <string>Select current working copy changes</string> + </property> + </widget> + </grid> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_startNumberButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>startNumberToggled(bool)</slot> + </connection> + <connection> + <sender>m_startHeadButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>startHeadToggled(bool)</slot> + </connection> + <connection> + <sender>m_startStartButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>startBaseToggled(bool)</slot> + </connection> + <connection> + <sender>m_stopStartButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>stopBaseToggled(bool)</slot> + </connection> + <connection> + <sender>m_stopHeadButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>stopHeadToggled(bool)</slot> + </connection> + <connection> + <sender>m_stopNumberButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>stopNumberToggled(bool)</slot> + </connection> + <connection> + <sender>m_stopDateButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>stopDateToggled(bool)</slot> + </connection> + <connection> + <sender>m_startDateButton</sender> + <signal>toggled(bool)</signal> + <receiver>RangeInput</receiver> + <slot>startDateToggled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_startNumberButton</tabstop> + <tabstop>m_startRevInput</tabstop> + <tabstop>m_startStartButton</tabstop> + <tabstop>m_startHeadButton</tabstop> + <tabstop>m_stopNumberButton</tabstop> + <tabstop>m_endRevInput</tabstop> + <tabstop>m_stopStartButton</tabstop> + <tabstop>m_stopHeadButton</tabstop> +</tabstops> +<slots> + <slot access="protected">stopHeadToggled(bool)</slot> + <slot access="protected">stopBaseToggled(bool)</slot> + <slot access="protected">stopNumberToggled(bool)</slot> + <slot access="protected">startHeadToggled(bool)</slot> + <slot access="protected">startBaseToggled(bool)</slot> + <slot access="protected">startNumberToggled(bool)</slot> + <slot access="protected">startDateToggled(bool)</slot> + <slot access="protected">stopDateToggled(bool)</slot> +</slots> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kdatetimewidget.h</includehint> + <includehint>kdatewidget.h</includehint> + <includehint>ktimewidget.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kdatetimewidget.h</includehint> + <includehint>kdatewidget.h</includehint> + <includehint>ktimewidget.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/fronthelpers/rangeinput_impl.cpp b/src/svnfrontend/fronthelpers/rangeinput_impl.cpp new file mode 100644 index 0000000..bf18bf9 --- /dev/null +++ b/src/svnfrontend/fronthelpers/rangeinput_impl.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "rangeinput_impl.h" +#include "helpers/sub2qt.h" + +#include <qpushbutton.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <knuminput.h> +#include <kdatetimewidget.h> +#include <qbuttongroup.h> +#include <klocale.h> +#include <kdebug.h> + +Rangeinput_impl::Rangeinput_impl(QWidget *parent, const char *name) + :RangeInputDlg(parent, name) +{ + m_startRevInput->setRange(0,INT_MAX,1,false); + m_endRevInput->setRange(0,INT_MAX,1,false); + m_startRevInput->setValue(1); + m_endRevInput->setValue(1); + m_startDateInput->setDateTime(QDateTime::currentDateTime ()); + m_stopDateInput->setDateTime(QDateTime::currentDateTime ()); + m_stopDateInput->setEnabled(false); + m_startDateInput->setEnabled(false); + m_stopHeadButton->setChecked(true); +} + +Rangeinput_impl::~Rangeinput_impl() +{ +} + +void Rangeinput_impl::startNumberToggled(bool how) +{ + m_startRevInput->setEnabled(how); + if (how) { + m_startDateInput->setEnabled(!how); + } +} + +void Rangeinput_impl::startBaseToggled(bool how) +{ + if (how) { + m_startRevInput->setEnabled(!how); + m_startDateInput->setEnabled(!how); + } +} + +void Rangeinput_impl::startHeadToggled(bool how) +{ + if (how) { + m_startRevInput->setEnabled(!how); + m_startDateInput->setEnabled(!how); + } +} + +void Rangeinput_impl::setNoWorking(bool aValue) +{ + if (!aValue) { + if (m_startWorkingButton->isChecked()) { + m_startHeadButton->setChecked(false); + } + if (m_stopWorkingButton->isChecked()) { + m_stopHeadButton->setChecked(false); + } + } + m_startWorkingButton->setEnabled(!aValue); + m_stopWorkingButton->setEnabled(!aValue); +} + +void Rangeinput_impl::onHelp() +{ +} + + +void Rangeinput_impl::stopHeadToggled(bool how) +{ + if (how) { + m_endRevInput->setEnabled(!how); + m_stopDateInput->setEnabled(!how); + } +} + + +void Rangeinput_impl::stopBaseToggled(bool how) +{ + if (how) { + m_endRevInput->setEnabled(!how); + m_stopDateInput->setEnabled(!how); + } +} + + +void Rangeinput_impl::stopNumberToggled(bool how) +{ + m_endRevInput->setEnabled(how); + if (how) { + m_stopDateInput->setEnabled(!how); + } +} + +Rangeinput_impl::revision_range Rangeinput_impl::getRange() +{ + revision_range ret; + if (m_startStartButton->isChecked()) { + ret.first = svn::Revision::START; + } else if (m_startHeadButton->isChecked()) { + ret.first = svn::Revision::HEAD; + } else if (m_startNumberButton->isChecked()) { + ret.first = m_startRevInput->value(); + } else if (m_startDateButton->isChecked()) { + ret.first=m_startDateInput->dateTime(); + } else if (m_startWorkingButton->isChecked()) { + ret.first = svn::Revision::WORKING; + } + if (m_stopStartButton->isChecked()) { + ret.second = svn::Revision::START; + } else if (m_stopHeadButton->isChecked()) { + ret.second = svn::Revision::HEAD; + } else if (m_stopNumberButton->isChecked()) { + ret.second = m_endRevInput->value(); + } else if (m_stopDateButton->isChecked()) { + ret.second=m_stopDateInput->dateTime(); + } else if (m_stopWorkingButton->isChecked()) { + ret.second = svn::Revision::WORKING; + } + return ret; +} + +void Rangeinput_impl::stopDateToggled(bool how) +{ + m_stopDateInput->setEnabled(how); + if (how) { + m_endRevInput->setEnabled(!how); + } +} + + +void Rangeinput_impl::startDateToggled(bool how) +{ + m_startDateInput->setEnabled(how); + if (how) { + m_startRevInput->setEnabled(!how); + } +} + + +bool Rangeinput_impl::StartOnly() const +{ + return m_StartOnly; +} + +void Rangeinput_impl::setHeadDefault() +{ + m_stopHeadButton->setChecked(true); + m_startHeadButton->setChecked(true); +} + +void Rangeinput_impl::setStartOnly(bool theValue) +{ + m_StartOnly = theValue; + if (m_StartOnly) { + RangeInputLayout->remove(m_stopRevBox); + m_stopRevBox->hide(); + m_startRevBox->setTitle(i18n("Select revision")); + } else { + RangeInputLayout->add(m_stopRevBox); + m_stopRevBox->show(); + m_startRevBox->setTitle(i18n( "Start with revision" )); + } + updateGeometry(); + setMinimumSize(minimumSizeHint()); + resize( QSize(397, 272).expandedTo(minimumSizeHint()) ); +} + +#include "rangeinput_impl.moc" diff --git a/src/svnfrontend/fronthelpers/rangeinput_impl.h b/src/svnfrontend/fronthelpers/rangeinput_impl.h new file mode 100644 index 0000000..a7ca29e --- /dev/null +++ b/src/svnfrontend/fronthelpers/rangeinput_impl.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef RANGEINPUT_IMPL_H +#define RANGEINPUT_IMPL_H + +#include "rangeinput.h" +#include "src/svnqt/revision.hpp" +#include <qpair.h> + +class Rangeinput_impl: public RangeInputDlg { +Q_OBJECT +public: + Rangeinput_impl(QWidget *parent = 0, const char *name = 0); + virtual ~Rangeinput_impl(); + + typedef QPair<svn::Revision,svn::Revision> revision_range; + + revision_range getRange(); + + virtual void setStartOnly(bool theValue); + virtual void setNoWorking(bool aValue); + + + bool StartOnly() const; + void setHeadDefault(); + +protected slots: + virtual void onHelp(); + virtual void stopHeadToggled(bool); + virtual void stopBaseToggled(bool); + virtual void stopNumberToggled(bool); + virtual void startHeadToggled(bool); + virtual void startBaseToggled(bool); + virtual void startNumberToggled(bool); + virtual void stopDateToggled(bool); + virtual void startDateToggled(bool); +protected: + bool m_StartOnly; +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/revisionbutton.ui b/src/svnfrontend/fronthelpers/revisionbutton.ui new file mode 100644 index 0000000..34b7b5a --- /dev/null +++ b/src/svnfrontend/fronthelpers/revisionbutton.ui @@ -0,0 +1,55 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>RevisionButton</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RevisionButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>124</width> + <height>28</height> + </rect> + </property> + <property name="caption"> + <string>RevisionButton</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_RevisionButton</cstring> + </property> + <property name="text"> + <string>-1</string> + </property> + </widget> + </hbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_RevisionButton</sender> + <signal>clicked()</signal> + <receiver>RevisionButton</receiver> + <slot>askRevision()</slot> + </connection> +</connections> +<slots> + <slot>askRevision()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/fronthelpers/revisionbuttonimpl.cpp b/src/svnfrontend/fronthelpers/revisionbuttonimpl.cpp new file mode 100644 index 0000000..15a2e6b --- /dev/null +++ b/src/svnfrontend/fronthelpers/revisionbuttonimpl.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "revisionbuttonimpl.h" +#include "src/svnfrontend/fronthelpers/rangeinput_impl.h" +#include "src/settings/kdesvnsettings.h" + +#include <kpushbutton.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kapplication.h> +#include <klocale.h> + +#include <qvbox.h> + +RevisionButtonImpl::RevisionButtonImpl(QWidget *parent, const char *name) + :RevisionButton(parent, name),m_Rev(svn::Revision::UNDEFINED),m_noWorking(false) +{ +} + +RevisionButtonImpl::~RevisionButtonImpl() +{ +} + +void RevisionButtonImpl::setRevision(const svn::Revision&aRev) +{ + m_Rev = aRev; + m_RevisionButton->setText(m_Rev.toString()); + emit revisionChanged(); +} + +void RevisionButtonImpl::askRevision() +{ + Rangeinput_impl*rdlg; + int buttons = KDialogBase::Ok|KDialogBase::Cancel; + + KDialogBase * dlg = new KDialogBase(KApplication::activeModalWidget(),"Revinput",true,i18n("Select revision"),buttons); + + if (!dlg) { + return; + } + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + rdlg = new Rangeinput_impl(Dialog1Layout); + rdlg->setStartOnly(true); + rdlg->setNoWorking(m_noWorking); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"log_revisions_dlg")); + if (dlg->exec()==QDialog::Accepted) { + setRevision(rdlg->getRange().first); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"log_revisions_dlg",false); + delete dlg; +} + +void RevisionButtonImpl::setNoWorking(bool how) +{ + m_noWorking = how; +} + +#include "revisionbuttonimpl.moc" diff --git a/src/svnfrontend/fronthelpers/revisionbuttonimpl.h b/src/svnfrontend/fronthelpers/revisionbuttonimpl.h new file mode 100644 index 0000000..a8f31a0 --- /dev/null +++ b/src/svnfrontend/fronthelpers/revisionbuttonimpl.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REVISIONBUTTONIMPL_H +#define REVISIONBUTTONIMPL_H + +#include "revisionbutton.h" +#include "svnqt/revision.hpp" + +class RevisionButtonImpl: public RevisionButton { + Q_OBJECT + +public: + RevisionButtonImpl(QWidget *parent = 0, const char *name = 0); + virtual ~RevisionButtonImpl(); + + virtual void setRevision(const svn::Revision&aRev); + + virtual void setNoWorking(bool); + const svn::Revision& revision()const { + return m_Rev; + } + +protected: + svn::Revision m_Rev; + bool m_noWorking; + +public slots: + virtual void askRevision(); +signals: + void revisionChanged(); + +}; + +#endif diff --git a/src/svnfrontend/fronthelpers/widgetblockstack.cpp b/src/svnfrontend/fronthelpers/widgetblockstack.cpp new file mode 100644 index 0000000..9b8af8f --- /dev/null +++ b/src/svnfrontend/fronthelpers/widgetblockstack.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "widgetblockstack.h" + +#include <qwidget.h> + +WidgetBlockStack::WidgetBlockStack(QWidget*w) +{ + if ( (_w=w)) + { + _w->setEnabled(false); + } +} + +WidgetBlockStack::~WidgetBlockStack() +{ + if (_w) + { + _w->setEnabled(true); + } +} diff --git a/src/svnfrontend/fronthelpers/widgetblockstack.h b/src/svnfrontend/fronthelpers/widgetblockstack.h new file mode 100644 index 0000000..88d24c5 --- /dev/null +++ b/src/svnfrontend/fronthelpers/widgetblockstack.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef __WIDGET_BLOCK_STACK_H +#define __WIDGET_BLOCK_STACK_H + +class QWidget; + +class WidgetBlockStack +{ + QWidget*_w; +public: + WidgetBlockStack(QWidget*); + ~WidgetBlockStack(); +}; + +#endif diff --git a/src/svnfrontend/graphtree/drawparams.cpp b/src/svnfrontend/graphtree/drawparams.cpp new file mode 100644 index 0000000..ced7bd4 --- /dev/null +++ b/src/svnfrontend/graphtree/drawparams.cpp @@ -0,0 +1,708 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + Adapted for the needs of kdesvn by Rajko Albrecht <ral@alwins-world.de> + + KCachegrind 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, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + */ + +#include <math.h> + +#include <qpainter.h> +#include <qtooltip.h> +#include <qregexp.h> +#include <qstyle.h> +#include <qpopupmenu.h> + +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> + +#include "drawparams.h" + + +// set this to 1 to enable debug output +#define DEBUG_DRAWING 0 +#define MAX_FIELD 12 + + +// +// StoredDrawParams +// +StoredDrawParams::StoredDrawParams() +{ + _selected = false; + _current = false; + _shaded = true; + _rotated = false; + + _backColor = Qt::white; + + // field array has size 0 +} + +StoredDrawParams::StoredDrawParams(QColor c, + bool selected, bool current) +{ + _backColor = c; + + _selected = selected; + _current = current; + _shaded = true; + _rotated = false; + _drawFrame = true; + + // field array has size 0 +} + +QString StoredDrawParams::text(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return QString::null; + + return _field[f].text; +} + +QPixmap StoredDrawParams::pixmap(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return QPixmap(); + + return _field[f].pix; +} + +DrawParams::Position StoredDrawParams::position(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return Default; + + return _field[f].pos; +} + +int StoredDrawParams::maxLines(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return 0; + + return _field[f].maxLines; +} + +const QFont& StoredDrawParams::font() const +{ + static QFont* f = 0; + if (!f) f = new QFont(QApplication::font()); + + return *f; +} + +void StoredDrawParams::ensureField(int f) +{ + static Field* def = 0; + if (!def) { + def = new Field(); + def->pos = Default; + def->maxLines = 0; + } + + if (f<0 || f>=MAX_FIELD) return; + + if ((int)_field.size() < f+1) _field.resize(f+1, *def); +} + + +void StoredDrawParams::setField(int f, QString t, QPixmap pm, + Position p, int maxLines) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].text = t; + _field[f].pix = pm; + _field[f].pos = p; + _field[f].maxLines = maxLines; +} + +void StoredDrawParams::setText(int f, QString t) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].text = t; +} + +void StoredDrawParams::setPixmap(int f, QPixmap pm) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].pix = pm; +} + +void StoredDrawParams::setPosition(int f, Position p) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].pos = p; +} + +void StoredDrawParams::setMaxLines(int f, int m) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].maxLines = m; +} + + + +// +// RectDrawing +// + +RectDrawing::RectDrawing(QRect r) +{ + _fm = 0; + _dp = 0; + setRect(r); +} + + +RectDrawing::~RectDrawing() +{ + delete _fm; + delete _dp; +} + +DrawParams* RectDrawing::drawParams() +{ + if (!_dp) + _dp = new StoredDrawParams(); + + return _dp; +} + + +void RectDrawing::setDrawParams(DrawParams* dp) +{ + if (_dp) delete _dp; + _dp = dp; +} + +void RectDrawing::setRect(QRect r) +{ + _rect = r; + + _usedTopLeft = 0; + _usedTopCenter = 0; + _usedTopRight = 0; + _usedBottomLeft = 0; + _usedBottomCenter = 0; + _usedBottomRight = 0; + + _fontHeight = 0; +} + +QRect RectDrawing::remainingRect(DrawParams* dp) +{ + if (!dp) dp = drawParams(); + + if ((_usedTopLeft >0) || + (_usedTopCenter >0) || + (_usedTopRight >0)) { + if (dp->rotated()) + _rect.setLeft(_rect.left() + _fontHeight); + else + _rect.setTop(_rect.top() + _fontHeight); + } + + if ((_usedBottomLeft >0) || + (_usedBottomCenter >0) || + (_usedBottomRight >0)) { + if (dp->rotated()) + _rect.setRight(_rect.right() - _fontHeight); + else + _rect.setBottom(_rect.bottom() - _fontHeight); + } + return _rect; +} + + +void RectDrawing::drawBack(QPainter* p, DrawParams* dp) +{ + if (!dp) dp = drawParams(); + if (_rect.width()<=0 || _rect.height()<=0) return; + + QRect r = _rect; + QColor normal = dp->backColor(); + if (dp->selected()) normal = normal.light(); + bool isCurrent = dp->current(); + + if (dp->drawFrame() || isCurrent) { + // 3D raised/sunken frame effect... + QColor high = normal.light(); + QColor low = normal.dark(); + p->setPen( isCurrent ? low:high); + p->drawLine(r.left(), r.top(), r.right(), r.top()); + p->drawLine(r.left(), r.top(), r.left(), r.bottom()); + p->setPen( isCurrent ? high:low); + p->drawLine(r.right(), r.top(), r.right(), r.bottom()); + p->drawLine(r.left(), r.bottom(), r.right(), r.bottom()); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + } + if (r.width()<=0 || r.height()<=0) return; + + if (dp->shaded()) { + // some shading + bool goDark = qGray(normal.rgb())>128; + int rBase, gBase, bBase; + normal.rgb(&rBase, &gBase, &bBase); + p->setBrush(QBrush::NoBrush); + + // shade parameters: + int d = 7; + float factor = 0.1, forth=0.7, back1 =0.9, toBack2 = .7, back2 = 0.97; + + // coefficient corrections because of rectangle size + int s = r.width(); + if (s > r.height()) s = r.height(); + if (s<100) { + forth -= .3 * (100-s)/100; + back1 -= .2 * (100-s)/100; + back2 -= .02 * (100-s)/100; + } + + + // maximal color difference + int rDiff = goDark ? -rBase/d : (255-rBase)/d; + int gDiff = goDark ? -gBase/d : (255-gBase)/d; + int bDiff = goDark ? -bBase/d : (255-bBase)/d; + + QColor shadeColor; + while (factor<.95) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + factor = 1.0 - ((1.0 - factor) * forth); + } + + // and back (1st half) + while (factor>toBack2) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + factor = 1.0 - ((1.0 - factor) / back1); + } + + // and back (2nd half) + while ( factor>.01) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + + factor = factor * back2; + } + } + + // fill inside + p->setPen(QPen::NoPen); + p->setBrush(normal); + p->drawRect(r); +} + + +bool RectDrawing::drawField(QPainter* p, int f, DrawParams* dp) +{ + if (!dp) dp = drawParams(); + + if (!_fm) { + _fm = new QFontMetrics(dp->font()); + _fontHeight = _fm->height(); + } + + QRect r = _rect; + + if (0) kdDebug(90100) << "DrawField: Rect " << r.x() << "/" << r.y() + << " - " << r.width() << "x" << r.height() << endl; + + int h = _fontHeight; + bool rotate = dp->rotated(); + int width = (rotate ? r.height() : r.width()) -4; + int height = (rotate ? r.width() : r.height()); + int lines = height / h; + + // stop if we have no space available + if (lines<1) return false; + + // calculate free space in first line (<unused>) + int pos = dp->position(f); + if (pos == DrawParams::Default) { + switch(f%4) { + case 0: pos = DrawParams::TopLeft; break; + case 1: pos = DrawParams::TopRight; break; + case 2: pos = DrawParams::BottomRight; break; + case 3: pos = DrawParams::BottomLeft; break; + } + } + + int unused = 0; + bool isBottom = false; + bool isCenter = false; + bool isRight = false; + int* used = 0; + switch(pos) { + case DrawParams::TopLeft: + used = &_usedTopLeft; + if (_usedTopLeft == 0) { + if (_usedTopCenter) + unused = (width - _usedTopCenter)/2; + else + unused = width - _usedTopRight; + } + break; + + case DrawParams::TopCenter: + isCenter = true; + used = &_usedTopCenter; + if (_usedTopCenter == 0) { + if (_usedTopLeft > _usedTopRight) + unused = width - 2 * _usedTopLeft; + else + unused = width - 2 * _usedTopRight; + } + break; + + case DrawParams::TopRight: + isRight = true; + used = &_usedTopRight; + if (_usedTopRight == 0) { + if (_usedTopCenter) + unused = (width - _usedTopCenter)/2; + else + unused = width - _usedTopLeft; + } + break; + + case DrawParams::BottomLeft: + isBottom = true; + used = &_usedBottomLeft; + if (_usedBottomLeft == 0) { + if (_usedBottomCenter) + unused = (width - _usedBottomCenter)/2; + else + unused = width - _usedBottomRight; + } + break; + + case DrawParams::BottomCenter: + isCenter = true; + isBottom = true; + used = &_usedBottomCenter; + if (_usedBottomCenter == 0) { + if (_usedBottomLeft > _usedBottomRight) + unused = width - 2 * _usedBottomLeft; + else + unused = width - 2 * _usedBottomRight; + } + break; + + case DrawParams::BottomRight: + isRight = true; + isBottom = true; + used = &_usedBottomRight; + if (_usedBottomRight == 0) { + if (_usedBottomCenter) + unused = (width - _usedBottomCenter)/2; + else + unused = width - _usedBottomLeft; + } + break; + } + + if (isBottom) { + if ((_usedTopLeft >0) || + (_usedTopCenter >0) || + (_usedTopRight >0)) + lines--; + } + else if (!isBottom) { + if ((_usedBottomLeft >0) || + (_usedBottomCenter >0) || + (_usedBottomRight >0)) + lines--; + } + if (lines<1) return false; + + + int y = isBottom ? height - h : 0; + + if (unused < 0) unused = 0; + if (unused == 0) { + // no space available in last line at this position + y = isBottom ? (y-h) : (y+h); + lines--; + + if (lines<1) return false; + + // new line: reset used space + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + + unused = width; + } + + // stop as soon as possible when there's no space for "..." + static int dotW = 0; + if (!dotW) dotW = _fm->width("..."); + if (width < dotW) return false; + + // get text and pixmap now, only if we need to, because it is possible + // that they are calculated on demand (and this can take some time) + QString name = dp->text(f); + if (name.isEmpty()) return 0; + QPixmap pix = dp->pixmap(f); + + // check if pixmap can be drawn + int pixW = pix.width(); + int pixH = pix.height(); + int pixY = 0; + bool pixDrawn = true; + if (pixW>0) { + pixW += 2; // X distance from pix + if ((width < pixW + dotW) || (height < pixH)) { + // don't draw + pixW = 0; + } + else + pixDrawn = false; + } + + // width of text and pixmap to be drawn + int w = pixW + _fm->width(name); + + if (0) kdDebug(90100) << " For '" << name << "': Unused " << unused + << ", StrW " << w << ", Width " << width << endl; + + // if we have limited space at 1st line: + // use it only if whole name does fit in last line... + if ((unused < width) && (w > unused)) { + y = isBottom ? (y-h) : (y+h); + lines--; + + if (lines<1) return false; + + // new line: reset used space + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + + p->save(); + p->setPen( (qGray(dp->backColor().rgb())>100) ? Qt::black : Qt::white); + p->setFont(dp->font()); + if (rotate) { + //p->translate(r.x()+2, r.y()+r.height()); + p->translate(r.x(), r.y()+r.height()-2); + p->rotate(270); + } + else + p->translate(r.x()+2, r.y()); + + + // adjust available lines according to maxLines + int max = dp->maxLines(f); + if ((max > 0) && (lines>max)) lines = max; + + /* loop over name parts to break up string depending on available width. + * every char category change is supposed a possible break, + * with the exception Uppercase=>Lowercase. + * It's good enough for numbers, Symbols... + * + * If the text is to be written at the bottom, we start with the + * end of the string (so everything is reverted) + */ + QString remaining; + int origLines = lines; + while (lines>0) { + + if (w>width && lines>1) { + int lastBreakPos = name.length(), lastWidth = w; + int len = name.length(); + QChar::Category caOld, ca; + + if (!isBottom) { + // start with comparing categories of last 2 chars + caOld = name[len-1].category(); + while (len>2) { + len--; + ca = name[len-1].category(); + if (ca != caOld) { + // "Aa" has no break between... + if (ca == QChar::Letter_Uppercase && + caOld == QChar::Letter_Lowercase) { + caOld = ca; + continue; + } + caOld = ca; + lastBreakPos = len; + w = pixW + _fm->width(name, len); + lastWidth = w; + if (w <= width) break; + } + } + w = lastWidth; + remaining = name.mid(lastBreakPos); + // remove space on break point + if (name[lastBreakPos-1].category() == QChar::Separator_Space) + name = name.left(lastBreakPos-1); + else + name = name.left(lastBreakPos); + } + else { // bottom + int l = len; + caOld = name[l-len].category(); + while (len>2) { + len--; + ca = name[l-len].category(); + + if (ca != caOld) { + // "Aa" has no break between... + if (caOld == QChar::Letter_Uppercase && + ca == QChar::Letter_Lowercase) { + caOld = ca; + continue; + } + caOld = ca; + lastBreakPos = len; + w = pixW + _fm->width(name.right(len)); + lastWidth = w; + if (w <= width) break; + } + } + w = lastWidth; + remaining = name.left(l-lastBreakPos); + // remove space on break point + if (name[l-lastBreakPos].category() == QChar::Separator_Space) + name = name.right(lastBreakPos-1); + else + name = name.right(lastBreakPos); + } + } + else + remaining = QString::null; + + /* truncate and add ... if needed */ + if (w>width) { + int len = name.length(); + w += dotW; + while (len>2 && (w > width)) { + len--; + w = pixW + _fm->width(name, len) + dotW; + } + // stop drawing: we cannot draw 2 chars + "..." + if (w>width) break; + + name = name.left(len) + "..."; + } + + int x = 0; + if (isCenter) + x = (width - w)/2; + else if (isRight) + x = width - w; + + if (!pixDrawn) { + pixY = y+(h-pixH)/2; // default: center vertically + if (pixH > h) pixY = isBottom ? y-(pixH-h) : y; + + p->drawPixmap( x, pixY, pix); + + // for distance to next text + pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2); + pixDrawn = true; + } + + + if (0) kdDebug(90100) << " Drawing '" << name << "' at " + << x+pixW << "/" << y << endl; + + p->drawText( x+pixW, y, + width - pixW, h, + Qt::AlignLeft, name); + y = isBottom ? (y-h) : (y+h); + lines--; + + if (remaining.isEmpty()) break; + name = remaining; + w = pixW + _fm->width(name); + } + + // make sure the pix stays visible + if (pixDrawn && (pixY>0)) { + if (isBottom && (pixY<y)) y = pixY; + if (!isBottom && (pixY>y)) y = pixY; + } + + if (origLines > lines) { + // if only 1 line written, don't reset _used* vars + if (lines - origLines >1) { + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + + // take back one line + y = isBottom ? (y+h) : (y-h); + if (used) *used = w; + } + + // update free space + if (!isBottom) { + if (rotate) + _rect.setRect(r.x()+y, r.y(), r.width()-y, r.height()); + else + _rect.setRect(r.x(), r.y()+y, r.width(), r.height()-y); + } + else { + if (rotate) + _rect.setRect(r.x(), r.y(), y+h, r.height()); + else + _rect.setRect(r.x(), r.y(), r.width(), y+h); + } + + p->restore(); + + return true; +} diff --git a/src/svnfrontend/graphtree/drawparams.h b/src/svnfrontend/graphtree/drawparams.h new file mode 100644 index 0000000..4898111 --- /dev/null +++ b/src/svnfrontend/graphtree/drawparams.h @@ -0,0 +1,200 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + Adapted for the needs of kdesvn by Rajko Albrecht <ral@alwins-world.de> + + KCachegrind 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, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + * + * This file defines the following classes: + * DrawParams, RectDrawing, TreeMapItem, TreeMapWidget + * + * DrawParams/RectDrawing allows reusing of TreeMap drawing + * functions in other widgets. + */ + +#ifndef DRAWPARAMS_H +#define DRAWPARAMS_H + +#include <qstring.h> +#include <qwidget.h> +#include <qpixmap.h> +#include <qptrlist.h> +#include <qvaluevector.h> +#include <qcolor.h> +#include <qapplication.h> +#include <qstringlist.h> + +class QPopupMenu; +class QString; + +class KConfigGroup; + + +/** + * Drawing parameters for an object. + * A Helper Interface for RectDrawing. + */ +class DrawParams +{ +public: + /** + * Positions for drawing into a rectangle. + * + * The specified position assumes no rotation. + * If there is more than one text for one position, it is put + * nearer to the center of the item. + * + * Drawing at top positions cuts free space from top, + * drawing at bottom positions cuts from bottom. + * Default usually gives positions clockwise according to field number. + */ + enum Position { TopLeft, TopCenter, TopRight, + BottomLeft, BottomCenter, BottomRight, + Default, Unknown}; + + // no constructor as this is an abstract class + virtual ~DrawParams() {} + + virtual QString text(int) const = 0; + virtual QPixmap pixmap(int) const = 0; + virtual Position position(int) const = 0; + // 0: no limit, negative: leave at least -maxLines() free + virtual int maxLines(int) const { return 0; } + virtual int fieldCount() const { return 0; } + + virtual QColor backColor() const { return Qt::white; } + virtual const QFont& font() const = 0; + + virtual bool selected() const { return false; } + virtual bool current() const { return false; } + virtual bool shaded() const { return true; } + virtual bool rotated() const { return false; } + virtual bool drawFrame() const { return true; } +}; + + +/* + * DrawParam with attributes stored + */ +class StoredDrawParams: public DrawParams +{ +public: + StoredDrawParams(); + StoredDrawParams(QColor c, + bool selected = false, bool current = false); + + // getters + QString text(int) const; + QPixmap pixmap(int) const; + Position position(int) const; + int maxLines(int) const; + int fieldCount() const { return _field.size(); } + + QColor backColor() const { return _backColor; } + bool selected() const { return _selected; } + bool current() const { return _current; } + bool shaded() const { return _shaded; } + bool rotated() const { return _rotated; } + bool drawFrame() const { return _drawFrame; } + + const QFont& font() const; + + // attribute setters + void setField(int f, QString t, QPixmap pm = QPixmap(), + Position p = Default, int maxLines = 0); + void setText(int f, QString); + void setPixmap(int f, QPixmap); + void setPosition(int f, Position); + void setMaxLines(int f, int); + void setBackColor(QColor c) { _backColor = c; } + void setSelected(bool b) { _selected = b; } + void setCurrent(bool b) { _current = b; } + void setShaded(bool b) { _shaded = b; } + void setRotated(bool b) { _rotated = b; } + void drawFrame(bool b) { _drawFrame = b; } + +protected: + QColor _backColor; + bool _selected :1; + bool _current :1; + bool _shaded :1; + bool _rotated :1; + bool _drawFrame :1; + +private: + // resize field array if needed to allow to access field <f> + void ensureField(int f); + + struct Field { + QString text; + QPixmap pix; + Position pos; + int maxLines; + }; + + QValueVector<Field> _field; +}; + + +/* State for drawing on a rectangle. + * + * Following drawing functions are provided: + * - background drawing with shading and 3D frame + * - successive pixmap/text drawing at various positions with wrap-around + * optimized for minimal space usage (e.g. if a text is drawn at top right + * after text on top left, the same line is used if space allows) + * + */ +class RectDrawing +{ +public: + RectDrawing(QRect); + ~RectDrawing(); + + // The default DrawParams object used. + DrawParams* drawParams(); + // we take control over the given object (i.e. delete at destruction) + void setDrawParams(DrawParams*); + + // draw on a given QPainter, use this class as info provider per default + void drawBack(QPainter*, DrawParams* dp = 0); + /* Draw field at position() from pixmap()/text() with maxLines(). + * Returns true if something was drawn + */ + bool drawField(QPainter*, int f, DrawParams* dp = 0); + + // resets rectangle for free space + void setRect(QRect); + + // Returns the rectangle area still free of text/pixmaps after + // a number of drawText() calls. + QRect remainingRect(DrawParams* dp = 0); + +private: + int _usedTopLeft, _usedTopCenter, _usedTopRight; + int _usedBottomLeft, _usedBottomCenter, _usedBottomRight; + QRect _rect; + + // temporary + int _fontHeight; + QFontMetrics* _fm; + DrawParams* _dp; +}; + +#endif diff --git a/src/svnfrontend/graphtree/elogentry.cpp b/src/svnfrontend/graphtree/elogentry.cpp new file mode 100644 index 0000000..924332c --- /dev/null +++ b/src/svnfrontend/graphtree/elogentry.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "elogentry.h" + +#include <kdebug.h> + +eLog_Entry::eLog_Entry(const svn::LogEntry&old) + : svn::LogEntry(old) +{ +} + +eLog_Entry::eLog_Entry() + : svn::LogEntry() +{ +} + +eLog_Entry::~eLog_Entry() +{ +} + +void eLog_Entry::addCopyTo(const QString¤t,const QString&target, + svn_revnum_t target_rev,char _action,svn_revnum_t from_rev) +{ + svn::LogChangePathEntry _entry; + _entry.copyToPath=target; + _entry.path = current; + _entry.copyToRevision = target_rev; + _entry.action=_action; + _entry.copyFromRevision = from_rev; + switch (_action) { + case 'A': + if (!target.isEmpty()) { + //kdDebug()<<"Adding a history "<< current << " -> " << target << endl; + _entry.action = 'H'; + }else{ + } + break; + case 'D': + break; + case 'R': +#if 0 + if (!target.isEmpty()) { + kdDebug()<<"Adding a rename "<< current << " -> " << target << endl; + } +#endif + break; + case 'M': + break; + default: + break; + } + /* make sure that ALL writing operations are BEFORE deletion of item, + * otherwise search will fail */ + if (_action=='D') { + changedPaths.push_back(_entry); + } else { + changedPaths.push_front(_entry); + } +} diff --git a/src/svnfrontend/graphtree/elogentry.h b/src/svnfrontend/graphtree/elogentry.h new file mode 100644 index 0000000..0fa63ef --- /dev/null +++ b/src/svnfrontend/graphtree/elogentry.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef ELOGENTRY_H +#define ELOGENTRY_H + +#include <svnqt/log_entry.hpp> + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +struct eLog_Entry : public svn::LogEntry +{ + eLog_Entry(); + eLog_Entry(const svn::LogEntry&); + ~eLog_Entry(); + + void addCopyTo(const QString&,const QString&,svn_revnum_t,char _action,svn_revnum_t fromRev=-1); + void addAction(const QString&,char _action); +}; +#endif diff --git a/src/svnfrontend/graphtree/graphtree_defines.h b/src/svnfrontend/graphtree/graphtree_defines.h new file mode 100644 index 0000000..596cb7d --- /dev/null +++ b/src/svnfrontend/graphtree/graphtree_defines.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2006 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef __GRAPHTREE_DEFINES +#define __GRAPHTREE_DEFINES + +enum { + GRAPHTREE_LABEL = 1100, + GRAPHTREE_LINE, + GRAPHTREE_ARROW, + GRAPHTREE_MARK +}; + +#endif diff --git a/src/svnfrontend/graphtree/graphtreelabel.cpp b/src/svnfrontend/graphtree/graphtreelabel.cpp new file mode 100644 index 0000000..9770fef --- /dev/null +++ b/src/svnfrontend/graphtree/graphtreelabel.cpp @@ -0,0 +1,220 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "graphtreelabel.h" +#include "graphtree_defines.h" +#include <qpainter.h> + +GraphTreeLabel::GraphTreeLabel(const QString&text, const QString&_nodename,const QRect&r,QCanvas*c) + : QCanvasRectangle(r,c),StoredDrawParams() +{ + m_Nodename = _nodename; + m_SourceNode = QString::null; + setText(0,text); + setPosition(0, DrawParams::TopCenter); + drawFrame(true); +} + +GraphTreeLabel::~GraphTreeLabel() +{ +} + +const QString&GraphTreeLabel::nodename()const +{ + return m_Nodename; +} + +int GraphTreeLabel::rtti()const +{ + return GRAPHTREE_LABEL; +} + +void GraphTreeLabel::setBgColor(const QColor&c) +{ + _backColor=c; +} + +void GraphTreeLabel::drawShape(QPainter& p) +{ + QRect r = rect(); +/* + p.setPen(blue); + p.drawRect(r); +*/ + RectDrawing d(r); + d.drawBack(&p,this); + d.drawField(&p, 0, this); + d.drawField(&p, 1, this); +} + +void GraphTreeLabel::setSelected(bool s) +{ + QCanvasRectangle::setSelected(s); + StoredDrawParams::setSelected(s); + update(); +} + +const QString&GraphTreeLabel::source()const +{ + return m_SourceNode; +} + +void GraphTreeLabel::setSource(const QString&_s) +{ + m_SourceNode=_s; +} + +GraphEdge::GraphEdge(QCanvas*c) + : QCanvasSpline(c) +{ +} + +GraphEdge::~GraphEdge() +{ +} + +void GraphEdge::drawShape(QPainter& p) +{ + p.drawPolyline(poly); +} + +QPointArray GraphEdge::areaPoints() const +{ + int minX = poly[0].x(), minY = poly[0].y(); + int maxX = minX, maxY = minY; + int i; + + if (0) qDebug("GraphEdge::areaPoints\n P 0: %d/%d", minX, minY); + int len = poly.count(); + for (i=1;i<len;i++) { + if (poly[i].x() < minX) minX = poly[i].x(); + if (poly[i].y() < minY) minY = poly[i].y(); + if (poly[i].x() > maxX) maxX = poly[i].x(); + if (poly[i].y() > maxY) maxY = poly[i].y(); + if (0) qDebug(" P %d: %d/%d", i, poly[i].x(), poly[i].y()); + } + QPointArray a = poly.copy(), b = poly.copy(); + if (minX == maxX) { + a.translate(-2, 0); + b.translate(2, 0); + } + else { + a.translate(0, -2); + b.translate(0, 2); + } + a.resize(2*len); + for (i=0;i<len;i++) + a[2 * len - 1 -i] = b[i]; + + if (0) { + qDebug(" Result:"); + for (i=0;i<2*len;i++) + qDebug(" P %d: %d/%d", i, a[i].x(), a[i].y()); + } + + return a; + +} + +int GraphEdge::rtti()const +{ + return GRAPHTREE_LINE; +} + +GraphEdgeArrow::GraphEdgeArrow(GraphEdge*_parent,QCanvas*c) + : QCanvasPolygon(c),_edge(_parent) +{ +} + +void GraphEdgeArrow::drawShape(QPainter&p) +{ + QCanvasPolygon::drawShape(p); +} + +int GraphEdgeArrow::rtti()const +{ + return GRAPHTREE_ARROW; +} + +GraphEdge*GraphEdgeArrow::edge() +{ + return _edge; +} + +/* taken from KCacheGrind project */ +QPixmap*GraphMark::_p=0; + +GraphMark::GraphMark(GraphTreeLabel*n,QCanvas*c) + : QCanvasRectangle(c) +{ + if (!_p) { + + int d = 5; + float v1 = 130.0, v2 = 10.0, v = v1, f = 1.03; + + // calculate pix size + QRect r(0, 0, 30, 30); + while (v>v2) { + r.setRect(r.x()-d, r.y()-d, r.width()+2*d, r.height()+2*d); + v /= f; + } + + _p = new QPixmap(r.size()); + _p->fill(Qt::white); + QPainter p(_p); + p.setPen(Qt::NoPen); + + r.moveBy(-r.x(), -r.y()); + + while (v<v1) { + v *= f; + p.setBrush(QColor(265-(int)v, 265-(int)v, 265-(int)v)); + + p.drawRect(QRect(r.x(), r.y(), r.width(), d)); + p.drawRect(QRect(r.x(), r.bottom()-d, r.width(), d)); + p.drawRect(QRect(r.x(), r.y()+d, d, r.height()-2*d)); + p.drawRect(QRect(r.right()-d, r.y()+d, d, r.height()-2*d)); + + r.setRect(r.x()+d, r.y()+d, r.width()-2*d, r.height()-2*d); + } + } + + setSize(_p->width(), _p->height()); + move(n->rect().center().x()-_p->width()/2, + n->rect().center().y()-_p->height()/2); +} + +GraphMark::~ GraphMark() +{ +} + +bool GraphMark::hit(const QPoint&)const +{ + return false; +} + +int GraphMark::rtti()const +{ + return GRAPHTREE_MARK; +} + +void GraphMark::drawShape(QPainter&p) +{ + p.drawPixmap( int(x()), int(y()), *_p ); +} diff --git a/src/svnfrontend/graphtree/graphtreelabel.h b/src/svnfrontend/graphtree/graphtreelabel.h new file mode 100644 index 0000000..dec788f --- /dev/null +++ b/src/svnfrontend/graphtree/graphtreelabel.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef GRAPHTREELABEL_H +#define GRAPHTREELABEL_H + +#include "graphtree/drawparams.h" +#include <qcanvas.h> + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class GraphTreeLabel : public QCanvasRectangle,StoredDrawParams +{ +public: + GraphTreeLabel(const QString&,const QString&,const QRect&r,QCanvas*c); + virtual ~GraphTreeLabel(); + + virtual int rtti()const; + virtual void drawShape(QPainter& p); + + void setBgColor(const QColor&); + + const QString&nodename()const; + const QString&source()const; + void setSource(const QString&); + virtual void setSelected(bool); + +protected: + QString m_Nodename; + QString m_SourceNode; +}; + +class GraphEdge; + +class GraphEdgeArrow:public QCanvasPolygon +{ +public: + GraphEdgeArrow(GraphEdge*,QCanvas*); + GraphEdge*edge(); + virtual void drawShape(QPainter&); + virtual int rtti()const; + +private: + GraphEdge*_edge; +}; + +/* line */ +class GraphEdge:public QCanvasSpline +{ +public: + GraphEdge(QCanvas*); + virtual ~GraphEdge(); + + virtual void drawShape(QPainter&); + QPointArray areaPoints() const; + virtual int rtti()const; +}; + +class GraphMark:public QCanvasRectangle +{ +public: + GraphMark(GraphTreeLabel*,QCanvas*); + virtual ~GraphMark(); + virtual int rtti()const; + virtual bool hit(const QPoint&)const; + + virtual void drawShape(QPainter&); +private: + static QPixmap*_p; +}; + +#endif diff --git a/src/svnfrontend/graphtree/pannerview.cpp b/src/svnfrontend/graphtree/pannerview.cpp new file mode 100644 index 0000000..5f14e82 --- /dev/null +++ b/src/svnfrontend/graphtree/pannerview.cpp @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "pannerview.h" +#include <qpainter.h> + +PannerView::PannerView(QWidget* parent, const char* name) + : QCanvasView(parent, name,WNoAutoErase | WStaticContents ) +{ + m_Moving = false; + viewport()->setBackgroundMode(Qt::NoBackground); + setBackgroundMode(Qt::NoBackground); +} + +PannerView::~PannerView() +{ +} + +void PannerView::drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph) +{ + p->save(); + QCanvasView::drawContents(p,clipx,clipy,clipw,cliph); + p->restore(); + if (m_ZoomRect.isValid()) { + p->setPen(red.dark()); + p->drawRect(m_ZoomRect); + p->setPen( red); + p->drawRect(QRect(m_ZoomRect.x()+1, m_ZoomRect.y()+1, + m_ZoomRect.width()-2, m_ZoomRect.height()-2)); + } +} + +void PannerView::setZoomRect(const QRect& theValue) +{ + QRect oldRect = m_ZoomRect; + m_ZoomRect = theValue; + updateContents(oldRect); + updateContents(m_ZoomRect); +} + +/*! + \fn PannerView::contentsMouseMoveEvent(QMouseEvent* e) + */ +void PannerView::contentsMouseMoveEvent(QMouseEvent* e) +{ + if (m_Moving) { + emit zoomRectMoved(e->pos().x() - m_LastPos.x(), e->pos().y() - m_LastPos.y()); + m_LastPos = e->pos(); + } +} + +/*! + \fn PannerView::contentsMousePressEvent(QMouseEvent* e) + */ +void PannerView::contentsMousePressEvent(QMouseEvent* e) +{ + if (m_ZoomRect.isValid()) { + if (!m_ZoomRect.contains(e->pos())) { + emit zoomRectMoved(e->pos().x() - m_ZoomRect.center().x(), + e->pos().y() - m_ZoomRect.center().y()); + } + m_Moving = true; + m_LastPos = e->pos(); + } +} + +/*! + \fn PannerView::contentsMouseReleaseEvent(QMouseEvent*) + */ +void PannerView::contentsMouseReleaseEvent(QMouseEvent*) +{ + m_Moving = false; + emit zoomRectMoveFinished(); +} + +/*! + \fn PannerView::updateCurrentRect() + */ +void PannerView::updateCurrentRect() +{ + if (m_ZoomRect.isValid()) updateContents(m_ZoomRect); +} + +#include "pannerview.moc" + diff --git a/src/svnfrontend/graphtree/pannerview.h b/src/svnfrontend/graphtree/pannerview.h new file mode 100644 index 0000000..6c1a310 --- /dev/null +++ b/src/svnfrontend/graphtree/pannerview.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef PANNERVIEW_H +#define PANNERVIEW_H + +#include <qcanvas.h> + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class PannerView : public QCanvasView +{ +Q_OBJECT +public: + PannerView(QWidget* parent=0, const char* name=0); + virtual ~PannerView(); + + void setZoomRect(const QRect& theValue); + void updateCurrentRect(); + +signals: + void zoomRectMoved(int dx, int dy); + void zoomRectMoveFinished(); + +protected: + virtual void drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph); + virtual void contentsMouseMoveEvent(QMouseEvent* e); + virtual void contentsMousePressEvent(QMouseEvent* e); + virtual void contentsMouseReleaseEvent(QMouseEvent*); +protected: + QRect m_ZoomRect; + bool m_Moving; + QPoint m_LastPos; +}; + +#endif diff --git a/src/svnfrontend/graphtree/revgraphview.cpp b/src/svnfrontend/graphtree/revgraphview.cpp new file mode 100644 index 0000000..cc85c0e --- /dev/null +++ b/src/svnfrontend/graphtree/revgraphview.cpp @@ -0,0 +1,950 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "revgraphview.h" +#include "graphtreelabel.h" +#include "pannerview.h" +#include "graphtree_defines.h" +#include "src/settings/kdesvnsettings.h" +#include "../stopdlg.h" +#include "src/svnqt/client.hpp" + +#include <kapp.h> +#include <kdebug.h> +#include <ktempfile.h> +#include <ktempdir.h> +#include <kprocess.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kmessagebox.h> + +#include <qtooltip.h> +#include <qwmatrix.h> +#include <qpopupmenu.h> +#include <qpainter.h> +#include <qregexp.h> + +#include <math.h> + +#define LABEL_WIDTH 160 +#define LABEL_HEIGHT 90 + + +class GraphViewTip:public QToolTip +{ +public: + GraphViewTip( QWidget* p ):QToolTip(p) {} + virtual ~GraphViewTip(){} + +protected: + void maybeTip( const QPoint & ); +}; + +void GraphViewTip::maybeTip( const QPoint & pos) +{ + if (!parentWidget()->inherits( "RevGraphView" )) return; + RevGraphView* cgv = (RevGraphView*)parentWidget(); + QPoint cPos = cgv->viewportToContents(pos); + QCanvasItemList l = cgv->canvas()->collisions(cPos); + if (l.count() == 0) return; + QCanvasItem* i = l.first(); + if (i->rtti() == GRAPHTREE_LABEL) { + GraphTreeLabel*tl = (GraphTreeLabel*)i; + QString nm = tl->nodename(); + QString tipStr = cgv->toolTip(nm); + if (tipStr.length()>0) { + QPoint vPosTL = cgv->contentsToViewport(i->boundingRect().topLeft()); + QPoint vPosBR = cgv->contentsToViewport(i->boundingRect().bottomRight()); + tip(QRect(vPosTL, vPosBR), tipStr); + } + } +} + +RevGraphView::RevGraphView(QObject*aListener,svn::Client*_client,QWidget * parent, const char * name, WFlags f) + : QCanvasView(parent,name,f) +{ + m_Canvas = 0L; + m_Client = _client; + m_Listener = aListener; + dotTmpFile = 0; + m_Selected = 0; + renderProcess = 0; + m_Marker = 0; + m_Tip = new GraphViewTip(this); + m_CompleteView = new PannerView(this); + m_CompleteView->setVScrollBarMode(QScrollView::AlwaysOff); + m_CompleteView->setHScrollBarMode(QScrollView::AlwaysOff); + m_CompleteView->raise(); + m_CompleteView->hide(); + connect(this, SIGNAL(contentsMoving(int,int)), + this, SLOT(contentsMovingSlot(int,int))); + connect(m_CompleteView, SIGNAL(zoomRectMoved(int,int)), + this, SLOT(zoomRectMoved(int,int))); + connect(m_CompleteView, SIGNAL(zoomRectMoveFinished()), + this, SLOT(zoomRectMoveFinished())); + m_LastAutoPosition = TopLeft; + _isMoving = false; + _noUpdateZoomerPos = false; + m_LabelMap[""]=""; +} + +RevGraphView::~RevGraphView() +{ + setCanvas(0); + delete m_Canvas; + delete dotTmpFile; + delete m_CompleteView; + delete m_Tip; + delete renderProcess; +} + +void RevGraphView::showText(const QString&s) +{ + clear(); + m_Canvas = new QCanvas(QApplication::desktop()->width(), + QApplication::desktop()->height()); + + QCanvasText* t = new QCanvasText(s, m_Canvas); + t->move(5, 5); + t->show(); + center(0,0); + setCanvas(m_Canvas); + m_Canvas->update(); + m_CompleteView->hide(); +} + +void RevGraphView::clear() +{ + if (m_Selected) { + m_Selected->setSelected(false); + m_Selected=0; + } + if (m_Marker) { + m_Marker->hide(); + delete m_Marker; + m_Marker=0; + } + if (!m_Canvas) return; + delete m_Canvas; + m_Canvas = 0; + setCanvas(0); + m_CompleteView->setCanvas(0); +} + +void RevGraphView::beginInsert() +{ + viewport()->setUpdatesEnabled(false); +} + +void RevGraphView::endInsert() +{ + if (m_Canvas) { + _cvZoom = 0; + updateSizes(); + m_Canvas->update(); + } + viewport()->setUpdatesEnabled(true); +} + +void RevGraphView::readDotOutput(KProcess*,char * buffer,int buflen) +{ + dotOutput+=QString::fromLocal8Bit(buffer, buflen); +} + +void RevGraphView::dotExit(KProcess*p) +{ + if (p!=renderProcess)return; + // remove line breaks when lines to long + QRegExp endslash("\\\\\\n"); + dotOutput.replace(endslash,""); + double scale = 1.0, scaleX = 1.0, scaleY = 1.0; + double dotWidth, dotHeight; + QTextStream* dotStream; + dotStream = new QTextStream(dotOutput, IO_ReadOnly); + QString line,cmd; + int lineno=0; + clear(); + beginInsert(); + /* mostly taken from kcachegrind */ + while (1) { + line = dotStream->readLine(); + if (line.isNull()) break; + lineno++; + if (line.isEmpty()) continue; + QTextStream lineStream(line, IO_ReadOnly); + lineStream >> cmd; + if (cmd == "stop") {break; } + + if (cmd == "graph") { + lineStream >> scale >> dotWidth >> dotHeight; + scaleX = scale * 60; scaleY = scale * 100; + int w = (int)(scaleX * dotWidth); + int h = (int)(scaleY * dotHeight); + + _xMargin = 50; + if (w < QApplication::desktop()->width()) + _xMargin += (QApplication::desktop()->width()-w)/2; + _yMargin = 50; + if (h < QApplication::desktop()->height()) + _yMargin += (QApplication::desktop()->height()-h)/2; + m_Canvas = new QCanvas(int(w+2*_xMargin), int(h+2*_yMargin)); + continue; + } + if ((cmd != "node") && (cmd != "edge")) { + kdWarning() << "Ignoring unknown command '" << cmd << "' from dot (" + << dotTmpFile->name() << ":" << lineno << ")" << endl; + continue; + } + if (cmd=="node") { + QString nodeName, label; + QString _x,_y,_w,_h; + double x, y, width, height; + lineStream >> nodeName >> _x >> _y >> _w >> _h; + x=_x.toDouble(); + y=_y.toDouble(); + width=_w.toDouble(); + height=_h.toDouble(); + // better here 'cause dot may scramble utf8 labels so we regenerate it better + // and do not read it in. + label = getLabelstring(nodeName); + int xx = (int)(scaleX * x + _xMargin); + int yy = (int)(scaleY * (dotHeight - y) + _yMargin); + int w = (int)(scaleX * width); + int h = (int)(scaleY * height); + QRect r(xx-w/2, yy-h/2, w, h); + GraphTreeLabel*t=new GraphTreeLabel(label,nodeName,r,m_Canvas); + if (isStart(nodeName)) { + ensureVisible(r.x(),r.y()); + } + t->setBgColor(getBgColor(nodeName)); + t->setZ(1.0); + t->show(); + m_NodeList[nodeName]=t; + } else { + QString node1Name, node2Name, label; + QString _x,_y; + double x, y; + QPointArray pa; + int points, i; + lineStream >> node1Name >> node2Name; + lineStream >> points; + pa.resize(points); + for (i=0;i<points;++i) { + if (lineStream.atEnd()) break; + lineStream >> _x >> _y; + x=_x.toDouble(); + y=_y.toDouble(); + int xx = (int)(scaleX * x + _xMargin); + int yy = (int)(scaleY * (dotHeight - y) + _yMargin); + + if (0) qDebug(" P %d: ( %f / %f ) => ( %d / %d)", + i, x, y, xx, yy); + pa.setPoint(i, xx, yy); + } + if (i < points) { + qDebug("CallGraphView: Can't read %d spline points (%d)", + points, lineno); + continue; + } + + GraphEdge * n = new GraphEdge(m_Canvas); + QColor arrowColor = Qt::black; + n->setPen(QPen(arrowColor,1)); + n->setControlPoints(pa,false); + n->setZ(0.5); + n->show(); + + /* arrow */ + QPoint arrowDir; + int indexHead = -1; + + QMap<QString,GraphTreeLabel*>::Iterator it; + it = m_NodeList.find(node2Name); + if (it!=m_NodeList.end()) { + it.data()->setSource(node1Name); + } + it = m_NodeList.find(node1Name); + if (it!=m_NodeList.end()) { + GraphTreeLabel*tlab = it.data(); + if (tlab) { + QPoint toCenter = tlab->rect().center(); + int dx0 = pa.point(0).x() - toCenter.x(); + int dy0 = pa.point(0).y() - toCenter.y(); + int dx1 = pa.point(points-1).x() - toCenter.x(); + int dy1 = pa.point(points-1).y() - toCenter.y(); + if (dx0*dx0+dy0*dy0 > dx1*dx1+dy1*dy1) { + // start of spline is nearer to call target node + indexHead=-1; + while(arrowDir.isNull() && (indexHead<points-2)) { + indexHead++; + arrowDir = pa.point(indexHead) - pa.point(indexHead+1); + } + } + } + } + + if (arrowDir.isNull()) { + indexHead = points; + // sometimes the last spline points from dot are the same... + while(arrowDir.isNull() && (indexHead>1)) { + indexHead--; + arrowDir = pa.point(indexHead) - pa.point(indexHead-1); + } + } + if (!arrowDir.isNull()) { + arrowDir *= 10.0/sqrt(double(arrowDir.x()*arrowDir.x() + + arrowDir.y()*arrowDir.y())); + QPointArray a(3); + a.setPoint(0, pa.point(indexHead) + arrowDir); + a.setPoint(1, pa.point(indexHead) + QPoint(arrowDir.y()/2, + -arrowDir.x()/2)); + a.setPoint(2, pa.point(indexHead) + QPoint(-arrowDir.y()/2, + arrowDir.x()/2)); + GraphEdgeArrow* aItem = new GraphEdgeArrow(n,m_Canvas); + aItem->setPoints(a); + aItem->setBrush(arrowColor); + aItem->setZ(1.5); + aItem->show(); +// sItem->setArrow(aItem); + } + } + } + if (!m_Canvas) { + QString s = i18n("Error running the graph layouting tool.\n"); + s += i18n("Please check that 'dot' is installed (package GraphViz)."); + showText(s); + } else { + setCanvas(m_Canvas); + m_CompleteView->setCanvas(m_Canvas); + } + endInsert(); + delete p; + renderProcess=0; +} + +bool RevGraphView::isStart(const QString&nodeName)const +{ + bool res = false; + trevTree::ConstIterator it; + it = m_Tree.find(nodeName); + if (it==m_Tree.end()) { + return res; + } + switch (it.data().Action) { + case 'A': + res = true; + break; + } + return res; +} + +char RevGraphView::getAction(const QString&nodeName)const +{ + trevTree::ConstIterator it; + it = m_Tree.find(nodeName); + if (it==m_Tree.end()) { + return (char)0; + } + return it.data().Action; +} + +QColor RevGraphView::getBgColor(const QString&nodeName)const +{ + trevTree::ConstIterator it; + it = m_Tree.find(nodeName); + QColor res = Qt::white; + if (it==m_Tree.end()) { + return res; + } + switch (it.data().Action) { + case 'D': + res = Kdesvnsettings::tree_delete_color(); + break; + case 'R': + case 'M': + res = Kdesvnsettings::tree_modify_color(); + break; + case 'A': + res = Kdesvnsettings::tree_add_color(); + break; + case 'C': + case 1: + res = Kdesvnsettings::tree_copy_color(); + break; + case 2: + res = Kdesvnsettings::tree_rename_color(); + break; + default: + res = Kdesvnsettings::tree_modify_color(); + break; + } + return res; +} + +const QString&RevGraphView::getLabelstring(const QString&nodeName) +{ + QMap<QString,QString>::ConstIterator nIt; + nIt = m_LabelMap.find(nodeName); + if (nIt!=m_LabelMap.end()) { + return nIt.data(); + } + trevTree::ConstIterator it1; + it1 = m_Tree.find(nodeName); + if (it1==m_Tree.end()) { + return m_LabelMap[""]; + } + QString res; + switch (it1.data().Action) { + case 'D': + res = i18n("Deleted at revision %1").arg(it1.data().rev); + break; + case 'A': + res = i18n("Added at revision %1 as %2") + .arg(it1.data().rev) + .arg(it1.data().name); + break; + case 'C': + case 1: + res = i18n("Copied to %1 at revision %2").arg(it1.data().name).arg(it1.data().rev); + break; + case 2: + res = i18n("Renamed to %1 at revision %2").arg(it1.data().name).arg(it1.data().rev); + break; + case 'M': + res = i18n("Modified at revision %1").arg(it1.data().rev); + break; + case 'R': + res = i18n("Replaced at revision %1").arg(it1.data().rev); + break; + default: + res=i18n("Revision %1").arg(it1.data().rev); + break; + } + m_LabelMap[nodeName]=res; + return m_LabelMap[nodeName]; +} + +void RevGraphView::dumpRevtree() +{ + delete dotTmpFile; + clear(); + dotOutput = ""; + dotTmpFile = new KTempFile(QString::null,".dot"); + dotTmpFile->setAutoDelete(true); + + QTextStream* stream = dotTmpFile->textStream(); + if (!stream) { + showText(i18n("Could not open tempfile %1 for writing.").arg(dotTmpFile->name())); + return; + } + + *stream << "digraph \"callgraph\" {\n"; + *stream << " bgcolor=\"transparent\";\n"; + int dir = Kdesvnsettings::tree_direction(); + *stream << QString(" rankdir=\""); + switch (dir) { + case 3: + *stream << "TB"; + break; + case 2: + *stream << "RL"; + break; + case 1: + *stream << "BT"; + break; + case 0: + default: + *stream << "LR"; + break; + } + *stream << "\";\n"; + + //*stream << QString(" overlap=false;\n splines=true;\n"); + + RevGraphView::trevTree::ConstIterator it1; + for (it1=m_Tree.begin();it1!=m_Tree.end();++it1) { + *stream << " " << it1.key() + << "[ " + << "shape=box, " + << "label=\""<<getLabelstring(it1.key())<<"\"," + << "];\n"; + for (unsigned j=0;j<it1.data().targets.count();++j) { + *stream<<" "<<it1.key().latin1()<< " " + << "->"<<" "<<it1.data().targets[j].key + << " [fontsize=10,style=\"solid\"];\n"; + } + } + *stream << "}\n"<<flush; + renderProcess = new KProcess(); + renderProcess->setEnvironment("LANG","C"); + *renderProcess << "dot"; + *renderProcess << dotTmpFile->name() << "-Tplain"; + connect(renderProcess,SIGNAL(processExited(KProcess*)),this,SLOT(dotExit(KProcess*))); + connect(renderProcess,SIGNAL(receivedStdout(KProcess*,char*,int)), + this,SLOT(readDotOutput(KProcess*,char*,int)) ); + if (!renderProcess->start(KProcess::NotifyOnExit,KProcess::Stdout)) { + QString arguments; + for (unsigned c=0;c<renderProcess->args().count();++c) { + arguments+=QString(" %1").arg(renderProcess->args()[c]); + } + QString error = i18n("Could not start process \"%1\".").arg(arguments); + showText(error); + renderProcess=0; + //delete renderProcess;< + } +} + +QString RevGraphView::toolTip(const QString&_nodename,bool full)const +{ + QString res = QString::null; + trevTree::ConstIterator it; + it = m_Tree.find(_nodename); + if (it==m_Tree.end()) { + return res; + } + QStringList sp = QStringList::split("\n",it.data().Message); + QString sm; + if (sp.count()==0) { + sm = it.data().Message; + } else { + if (!full) { + sm = sp[0]+"..."; + } else { + for (unsigned j = 0; j<sp.count(); ++j) { + if (j>0) sm+="<br>"; + sm+=sp[j]; + } + } + } + if (!full && sm.length()>50) { + sm.truncate(47); + sm+="..."; + } + static QString csep = "</td><td>"; + static QString rend = "</td></tr>"; + static QString rstart = "<tr><td>"; + res = QString("<html><body>"); + + if (!full) { + res+=QString("<b>%1</b>").arg(it.data().name); + res += i18n("<br>Revision: %1<br>Author: %2<br>Date: %3<br>Log: %4</html>") + .arg(it.data().rev) + .arg(it.data().Author) + .arg(it.data().Date) + .arg(sm); + } else { + res+="<table><tr><th colspan=\"2\"><b>"+it.data().name+"</b></th></tr>"; + res+=rstart; + res+=i18n("<b>Revision</b>%1%2%3").arg(csep).arg(it.data().rev).arg(rend); + res+=rstart+i18n("<b>Author</b>%1%2%3").arg(csep).arg(it.data().Author).arg(rend); + res+=rstart+i18n("<b>Date</b>%1%2%3").arg(csep).arg(it.data().Date).arg(rend); + res+=rstart+i18n("<b>Log</b>%1%2%3").arg(csep).arg(sm).arg(rend); + res+="</table></body></html>"; + } + return res; +} + +void RevGraphView::updateSizes(QSize s) +{ + if (!m_Canvas) return; + if (s == QSize(0,0)) s = size(); + + // the part of the canvas that should be visible + int cWidth = m_Canvas->width() - 2*_xMargin + 100; + int cHeight = m_Canvas->height() - 2*_yMargin + 100; + + // hide birds eye view if no overview needed + if (((cWidth < s.width()) && cHeight < s.height())||m_NodeList.count()==0) { + m_CompleteView->hide(); + return; + } + + m_CompleteView->show(); + + // first, assume use of 1/3 of width/height (possible larger) + double zoom = .33 * s.width() / cWidth; + if (zoom * cHeight < .33 * s.height()) zoom = .33 * s.height() / cHeight; + + // fit to widget size + if (cWidth * zoom > s.width()) zoom = s.width() / (double)cWidth; + if (cHeight * zoom > s.height()) zoom = s.height() / (double)cHeight; + + // scale to never use full height/width + zoom = zoom * 3/4; + + // at most a zoom of 1/3 + if (zoom > .33) zoom = .33; + + if (zoom != _cvZoom) { + _cvZoom = zoom; + if (0) qDebug("Canvas Size: %dx%d, Visible: %dx%d, Zoom: %f", + m_Canvas->width(), m_Canvas->height(), + cWidth, cHeight, zoom); + + QWMatrix wm; + wm.scale( zoom, zoom ); + m_CompleteView->setWorldMatrix(wm); + + // make it a little bigger to compensate for widget frame + m_CompleteView->resize(int(cWidth * zoom) + 4, + int(cHeight * zoom) + 4); + + // update ZoomRect in completeView + contentsMovingSlot(contentsX(), contentsY()); + } + + m_CompleteView->setContentsPos(int(zoom*(_xMargin-50)), + int(zoom*(_yMargin-50))); + updateZoomerPos(); +} + +void RevGraphView::updateZoomerPos() +{ + int cvW = m_CompleteView->width(); + int cvH = m_CompleteView->height(); + int x = width()- cvW - verticalScrollBar()->width() -2; + int y = height()-cvH - horizontalScrollBar()->height() -2; + + QPoint oldZoomPos = m_CompleteView->pos(); + QPoint newZoomPos = QPoint(0,0); + +#if 0 + ZoomPosition zp = _zoomPosition; + if (zp == Auto) { +#else + ZoomPosition zp = m_LastAutoPosition; +#endif + QPoint tl1Pos = viewportToContents(QPoint(0,0)); + QPoint tl2Pos = viewportToContents(QPoint(cvW,cvH)); + QPoint tr1Pos = viewportToContents(QPoint(x,0)); + QPoint tr2Pos = viewportToContents(QPoint(x+cvW,cvH)); + QPoint bl1Pos = viewportToContents(QPoint(0,y)); + QPoint bl2Pos = viewportToContents(QPoint(cvW,y+cvH)); + QPoint br1Pos = viewportToContents(QPoint(x,y)); + QPoint br2Pos = viewportToContents(QPoint(x+cvW,y+cvH)); + int tlCols = m_Canvas->collisions(QRect(tl1Pos,tl2Pos)).count(); + int trCols = m_Canvas->collisions(QRect(tr1Pos,tr2Pos)).count(); + int blCols = m_Canvas->collisions(QRect(bl1Pos,bl2Pos)).count(); + int brCols = m_Canvas->collisions(QRect(br1Pos,br2Pos)).count(); + int minCols = tlCols; + zp = m_LastAutoPosition; + switch(zp) { + case TopRight: minCols = trCols; break; + case BottomLeft: minCols = blCols; break; + case BottomRight: minCols = brCols; break; + default: + case TopLeft: minCols = tlCols; break; + } + if (minCols > tlCols) { minCols = tlCols; zp = TopLeft; } + if (minCols > trCols) { minCols = trCols; zp = TopRight; } + if (minCols > blCols) { minCols = blCols; zp = BottomLeft; } + if (minCols > brCols) { minCols = brCols; zp = BottomRight; } + + m_LastAutoPosition = zp; +#if 0 + } +#endif + switch(zp) { + case TopRight: + newZoomPos = QPoint(x,0); + break; + case BottomLeft: + newZoomPos = QPoint(0,y); + break; + case BottomRight: + newZoomPos = QPoint(x,y); + break; + default: + break; + } + if (newZoomPos != oldZoomPos) m_CompleteView->move(newZoomPos); +} + +void RevGraphView::contentsMovingSlot(int x,int y) +{ + QRect z(int(x * _cvZoom), int(y * _cvZoom), + int(visibleWidth() * _cvZoom)-1, int(visibleHeight() * _cvZoom)-1); + if (0) qDebug("moving: (%d,%d) => (%d/%d - %dx%d)", + x, y, z.x(), z.y(), z.width(), z.height()); + m_CompleteView->setZoomRect(z); + if (!_noUpdateZoomerPos) { + updateZoomerPos(); + } +} + +void RevGraphView::zoomRectMoved(int dx,int dy) +{ + if (leftMargin()>0) dx = 0; + if (topMargin()>0) dy = 0; + _noUpdateZoomerPos = true; + scrollBy(int(dx/_cvZoom),int(dy/_cvZoom)); + _noUpdateZoomerPos = false; +} + +void RevGraphView::zoomRectMoveFinished() +{ +#if 0 + if (_zoomPosition == Auto) +#endif + updateZoomerPos(); +} + +void RevGraphView::resizeEvent(QResizeEvent*e) +{ + QCanvasView::resizeEvent(e); + if (m_Canvas) updateSizes(e->size()); +} + +void RevGraphView::makeSelected(GraphTreeLabel*gtl) +{ + if (m_Selected) { + m_Selected->setSelected(false); + } + m_Selected=gtl; + if (m_Marker) { + m_Marker->hide(); + delete m_Marker; + m_Marker=0; + } + if (gtl) { + m_Marker = new GraphMark(gtl,m_Canvas); + m_Marker->setZ(-1); + m_Marker->show(); + m_Selected->setSelected(true); + } + m_Canvas->update(); + m_CompleteView->updateCurrentRect(); +} + +void RevGraphView::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + setFocus(); + if (e->button() == Qt::LeftButton) { + QCanvasItemList l = canvas()->collisions(e->pos()); + if (l.count()>0) { + QCanvasItem* i = l.first(); + if (i->rtti()==GRAPHTREE_LABEL) { + makeSelected( (GraphTreeLabel*)i); + emit dispDetails(toolTip(((GraphTreeLabel*)i)->nodename(),true)); + } + } + } +} + +void RevGraphView::contentsMousePressEvent ( QMouseEvent * e ) +{ + setFocus(); + _isMoving = true; + _lastPos = e->globalPos(); +} + +void RevGraphView::contentsMouseReleaseEvent ( QMouseEvent * ) +{ + _isMoving = false; + updateZoomerPos(); +} + +void RevGraphView::contentsMouseMoveEvent ( QMouseEvent * e ) +{ + if (_isMoving) { + int dx = e->globalPos().x() - _lastPos.x(); + int dy = e->globalPos().y() - _lastPos.y(); + _noUpdateZoomerPos = true; + scrollBy(-dx, -dy); + _noUpdateZoomerPos = false; + _lastPos = e->globalPos(); + } +} + +void RevGraphView::setNewDirection(int dir) +{ + if (dir<0)dir=3; + else if (dir>3)dir=0; + Kdesvnsettings::setTree_direction(dir); + dumpRevtree(); +} + +void RevGraphView::contentsContextMenuEvent(QContextMenuEvent* e) +{ + if (!m_Canvas) return; + QCanvasItemList l = canvas()->collisions(e->pos()); + QCanvasItem* i = (l.count() == 0) ? 0 : l.first(); + + QPopupMenu popup; + if (i && i->rtti()==GRAPHTREE_LABEL) { + if (!((GraphTreeLabel*)i)->source().isEmpty() && getAction(((GraphTreeLabel*)i)->nodename())!='D') { + popup.insertItem(i18n("Diff to previous"),301); + } + if (m_Selected && m_Selected != i && getAction(m_Selected->nodename())!='D' + && getAction(((GraphTreeLabel*)i)->nodename())!='D') { + popup.insertItem(i18n("Diff to selected item"),302); + } + if (getAction(((GraphTreeLabel*)i)->nodename())!='D') { + popup.insertItem(i18n("Cat this version"),303); + } + if (m_Selected == i) { + popup.insertItem(i18n("Unselect item"),401); + } else { + popup.insertItem(i18n("Select item"),402); + } + popup.insertSeparator(); + popup.insertItem(i18n("Display details"),403); + popup.insertSeparator(); + } + popup.insertItem(i18n("Rotate counter-clockwise"),101); + popup.insertItem(i18n("Rotate clockwise"),102); + popup.insertSeparator(); + int it = popup.insertItem(i18n("Diff in revisiontree is recursive"),202); + popup.setCheckable(true); + popup.setItemChecked(it,Kdesvnsettings::tree_diff_rec()); + popup.insertItem(i18n("Save tree as png"),201); + + int r = popup.exec(e->globalPos()); + + switch (r) { + case 101: + { + int dir = Kdesvnsettings::tree_direction(); + setNewDirection(++dir); + } + break; + case 102: + { + int dir = Kdesvnsettings::tree_direction(); + setNewDirection(--dir); + } + break; + case 201: + { + QString fn = KFileDialog::getSaveFileName(":","*.png"); + if (!fn.isEmpty()) { + if (m_Marker) { + m_Marker->hide(); + } + if (m_Selected) { + m_Selected->setSelected(false); + } + QPixmap pix(m_Canvas->size()); + QPainter p(&pix); + m_Canvas->drawArea( m_Canvas->rect(), &p ); + pix.save(fn,"PNG"); + if (m_Marker) { + m_Marker->show(); + } + if (m_Selected) { + m_Selected->setSelected(true); + m_Canvas->update(); + m_CompleteView->updateCurrentRect(); + } + } + } + case 202: + { + Kdesvnsettings::setTree_diff_rec(!Kdesvnsettings::tree_diff_rec()); + break; + } + break; + case 301: + if (i && i->rtti()==GRAPHTREE_LABEL && !((GraphTreeLabel*)i)->source().isEmpty()) { + makeDiffPrev((GraphTreeLabel*)i); + } + break; + case 302: + if (i && i->rtti()==GRAPHTREE_LABEL && m_Selected) { + makeDiff(((GraphTreeLabel*)i)->nodename(),m_Selected->nodename()); + } + break; + case 303: + if (i && i->rtti()==GRAPHTREE_LABEL) { + makeCat((GraphTreeLabel*)i); + } + break; + case 401: + makeSelected(0); + break; + case 402: + makeSelected((GraphTreeLabel*)i); + break; + case 403: + emit dispDetails(toolTip(((GraphTreeLabel*)i)->nodename(),true)); + break; + default: + break; + } +} + +void RevGraphView::makeCat(GraphTreeLabel*_l) +{ + if (!_l) { + return; + } + QString n1 = _l->nodename(); + trevTree::ConstIterator it = m_Tree.find(n1); + if (it==m_Tree.end()) { + return; + } + svn::Revision tr(it.data().rev); + QString tp = _basePath+it.data().name; + emit makeCat(tr,tp,it.data().name,tr,kapp->activeModalWidget()); +} + +void RevGraphView::makeDiffPrev(GraphTreeLabel*_l) +{ + if (!_l) return; + QString n1,n2; + n1 = _l->nodename(); + n2 = _l->source(); + makeDiff(n1,n2); +} + +void RevGraphView::makeDiff(const QString&n1,const QString&n2) +{ + if (n1.isEmpty()||n2.isEmpty()) return; + trevTree::ConstIterator it; + it = m_Tree.find(n2); + if (it==m_Tree.end()) { + return; + } + svn::Revision sr(it.data().rev); + QString sp = _basePath+it.data().name; + + it = m_Tree.find(n1); + if (it==m_Tree.end()) { + return; + } + svn::Revision tr(it.data().rev); + QString tp = _basePath+it.data().name; + if (Kdesvnsettings::tree_diff_rec()) { + emit makeRecDiff(sp,sr,tp,tr,kapp->activeModalWidget()); + } else { + emit makeNorecDiff(sp,sr,tp,tr,kapp->activeModalWidget()); + } +} + +void RevGraphView::setBasePath(const QString&_path) +{ + _basePath = _path; +} + +void RevGraphView::slotClientException(const QString&what) +{ + KMessageBox::sorry(KApplication::activeModalWidget(),what,i18n("SVN Error")); +} + +#include "revgraphview.moc" diff --git a/src/svnfrontend/graphtree/revgraphview.h b/src/svnfrontend/graphtree/revgraphview.h new file mode 100644 index 0000000..039bc4b --- /dev/null +++ b/src/svnfrontend/graphtree/revgraphview.h @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REVGRAPHVIEW_H +#define REVGRAPHVIEW_H + +#include <svnqt/revision.hpp> + +#include <qcanvas.h> + +namespace svn { + class LogEntry; + class Client; +} + +class KTempFile; +class KProcess; +class RevisionTree; +class GraphTreeLabel; +class GraphViewTip; +class GraphMark; +class PannerView; +class CContextListener; + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class RevGraphView : public QCanvasView +{ + Q_OBJECT +public: + enum ZoomPosition { TopLeft, TopRight, BottomLeft, BottomRight, Auto }; + /* avoid large copy operations */ + friend class RevisionTree; + + RevGraphView(QObject*,svn::Client*,QWidget * parent = 0, const char * name = 0, WFlags f = 0); + virtual ~RevGraphView(); + + void showText(const QString&s); + void clear(); + + void beginInsert(); + void endInsert(); + + struct targetData { + char Action; + QString key; + targetData(const QString&n,char _a) + { + key = n; + Action = _a; + } + targetData(){Action=0;key="";} + }; + typedef QValueList<targetData> tlist; + + struct keyData { + QString name,Author,Date,Message; + long rev; + char Action; + tlist targets; + }; + + typedef QMap<QString,keyData> trevTree; + + QString toolTip(const QString&nodename,bool full=false)const; + + void setBasePath(const QString&); + void dumpRevtree(); + +signals: + void dispDetails(const QString&); + void makeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*); + void makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + void makeRecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + +public slots: + virtual void contentsMovingSlot(int,int); + virtual void zoomRectMoved(int,int); + virtual void zoomRectMoveFinished(); + virtual void slotClientException(const QString&what); + +protected slots: + virtual void readDotOutput(KProcess * proc,char * buffer,int buflen); + virtual void dotExit(KProcess*); + +protected: + QCanvas*m_Canvas; + GraphMark*m_Marker; + svn::Client*m_Client; + GraphTreeLabel*m_Selected; + QObject*m_Listener; + KTempFile*dotTmpFile; + QString dotOutput; + KProcess*renderProcess; + trevTree m_Tree; + QColor getBgColor(const QString&nodeName)const; + bool isStart(const QString&nodeName)const; + char getAction(const QString&)const; + const QString&getLabelstring(const QString&nodeName); + + QMap<QString,GraphTreeLabel*> m_NodeList; + QMap<QString,QString> m_LabelMap; + + int _xMargin,_yMargin; + GraphViewTip*m_Tip; + PannerView*m_CompleteView; + double _cvZoom; + ZoomPosition m_LastAutoPosition; + + virtual void resizeEvent(QResizeEvent*); + virtual void contentsMousePressEvent ( QMouseEvent * e ); + virtual void contentsMouseReleaseEvent ( QMouseEvent * e ); + virtual void contentsMouseMoveEvent ( QMouseEvent*e); + virtual void contentsContextMenuEvent(QContextMenuEvent*e); + virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e ); + + bool _isMoving; + QPoint _lastPos; + + bool _noUpdateZoomerPos; + + QString _basePath; + +private: + void updateSizes(QSize s = QSize(0,0)); + void updateZoomerPos(); + void setNewDirection(int dir); + void makeDiffPrev(GraphTreeLabel*); + void makeDiff(const QString&,const QString&); + void makeSelected(GraphTreeLabel*); + void makeCat(GraphTreeLabel*_l); +}; + +#endif diff --git a/src/svnfrontend/graphtree/revisiontree.cpp b/src/svnfrontend/graphtree/revisiontree.cpp new file mode 100644 index 0000000..bb64cf7 --- /dev/null +++ b/src/svnfrontend/graphtree/revisiontree.cpp @@ -0,0 +1,544 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "revisiontree.h" +#include "../stopdlg.h" +#include "src/svnqt/log_entry.hpp" +#include "src/svnqt/cache/LogCache.hpp" +#include "src/svnqt/cache/ReposLog.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/sub2qt.h" +#include "revtreewidget.h" +#include "revgraphview.h" +#include "elogentry.h" +#include "src/svnfrontend/fronthelpers/cursorstack.h" +#include "src/settings/kdesvnsettings.h" + +#include <kdebug.h> +#include <kprogress.h> +#include <klocale.h> +#include <kapp.h> +#include <klistview.h> +#include <kmdcodec.h> +#include <kmessagebox.h> + +#include <qwidget.h> +#include <qdatetime.h> +#include <qlabel.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#define INTERNALCOPY 1 +#define INTERNALRENAME 2 + +class RtreeData +{ +public: + RtreeData(); + virtual ~RtreeData(); + + QMap<long,eLog_Entry> m_History; + + svn::LogEntriesMap m_OldHistory; + + long max_rev,min_rev; + KProgressDialog*progress; + QTime m_stopTick; + + QWidget*dlgParent; + RevTreeWidget*m_TreeDisplay; + + svn::Client*m_Client; + QObject* m_Listener; + + bool getLogs(const QString&,const svn::Revision&startr,const svn::Revision&endr,const QString&origin); +}; + +RtreeData::RtreeData() + : max_rev(-1),min_rev(-1) +{ + progress=0; + m_TreeDisplay = 0; + m_Client = 0; + dlgParent = 0; + m_Listener = 0; +} + +RtreeData::~RtreeData() +{ + delete progress; +} + +bool RtreeData::getLogs(const QString&reposRoot,const svn::Revision&startr,const svn::Revision&endr,const QString&origin) +{ + if (!m_Listener||!m_Client) { + return false; + } + try { + CursorStack a(Qt::BusyCursor); + StopDlg sdlg(m_Listener,dlgParent, + 0,"Logs",i18n("Getting logs - hit cancel for abort")); + if (svn::Url::isLocal(reposRoot) ) { + m_Client->log(reposRoot,endr,startr,m_OldHistory,startr,true,false,0); + } else { + svn::cache::ReposLog rl(m_Client,reposRoot); + if (rl.isValid()) { + rl.simpleLog(m_OldHistory,startr,endr,!Kdesvnsettings::network_on()); + } else if (Kdesvnsettings::network_on()) { + m_Client->log(reposRoot,endr,startr,m_OldHistory,startr,true,false,0); + } else { + KMessageBox::error(0,i18n("Could not retrieve logs, reason:\n%1").arg(i18n("No logcache possible due broken database and networking not allowed."))); + return false; + } + } + } catch (const svn::Exception&ce) { + kdDebug()<<ce.msg() << endl; + KMessageBox::error(0,i18n("Could not retrieve logs, reason:\n%1").arg(ce.msg())); + return false; + } + return true; +} + +RevisionTree::RevisionTree(svn::Client*aClient, + QObject*aListener, + const QString& reposRoot, + const svn::Revision&startr,const svn::Revision&endr, + const QString&origin, + const svn::Revision& baserevision, + QWidget*treeParent,QWidget*parent) + :m_InitialRevsion(0),m_Path(origin),m_Valid(false) +{ + m_Data = new RtreeData; + m_Data->m_Client=aClient; + m_Data->m_Listener=aListener; + m_Data->dlgParent=parent; + + if (!m_Data->getLogs(reposRoot,startr,endr,origin)) { + return; + } + + long possible_rev=-1; + kdDebug()<<"Origin: "<<origin << endl; + + m_Data->progress=new KProgressDialog( + parent,"progressdlg",i18n("Scanning logs"),i18n("Scanning the logs for %1").arg(origin),true); + m_Data->progress->setMinimumDuration(100); + m_Data->progress->show(); + m_Data->progress->setAllowCancel(true); + m_Data->progress->progressBar()->setTotalSteps(m_Data->m_OldHistory.size()); + m_Data->progress->setAutoClose(false); + m_Data->progress->show(); + bool cancel=false; + svn::LogEntriesMap::Iterator it; + unsigned count = 0; + for (it=m_Data->m_OldHistory.begin();it!=m_Data->m_OldHistory.end();++it) { + m_Data->progress->progressBar()->setProgress(count); + kapp->processEvents(); + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + if (it.key()>m_Data->max_rev) { + m_Data->max_rev=it.key(); + } + if (it.key()<m_Data->min_rev||m_Data->min_rev==-1) { + m_Data->min_rev=it.key(); + } + if (baserevision.kind()==svn_opt_revision_date) { + if (baserevision.date()<=it.data().date && possible_rev==-1||possible_rev>it.key()) { + possible_rev=it.key(); + } + } + ++count; + } + if (baserevision.kind()==svn_opt_revision_head||baserevision.kind()==svn_opt_revision_working) { + m_Baserevision=m_Data->max_rev; + } else if (baserevision.kind()==svn_opt_revision_number) { + m_Baserevision=baserevision.revnum(); + } else if (baserevision.kind()==svn_opt_revision_date) { + m_Baserevision=possible_rev; + } + if (!cancel) { + kdDebug( )<<" max revision " << m_Data->max_rev + << " min revision " << m_Data->min_rev << endl; + if (topDownScan()) { + kdDebug()<<"topdown end"<<endl; + m_Data->progress->setAutoReset(true); + m_Data->progress->progressBar()->setTotalSteps(100); + m_Data->progress->progressBar()->setPercentageVisible(false); + m_Data->m_stopTick.restart(); + m_Data->m_TreeDisplay=new RevTreeWidget(m_Data->m_Listener,m_Data->m_Client,treeParent); + if (bottomUpScan(m_InitialRevsion,0,m_Path,0)) { + kdDebug()<<"Bottom up end"<<endl; + m_Valid=true; + m_Data->m_TreeDisplay->setBasePath(reposRoot); + m_Data->m_TreeDisplay->dumpRevtree(); + } else { + delete m_Data->m_TreeDisplay; + m_Data->m_TreeDisplay = 0; + } + } + } else { + kdDebug()<<"Canceld"<<endl; + } + m_Data->progress->hide(); +} + +RevisionTree::~RevisionTree() +{ + delete m_Data; +} + +bool RevisionTree::isDeleted(long revision,const QString&path) +{ + for (unsigned i = 0;i<m_Data->m_History[revision].changedPaths.count();++i) { + if (isParent(m_Data->m_History[revision].changedPaths[i].path,path) && + m_Data->m_History[revision].changedPaths[i].action=='D') { + return true; + } + } + return false; +} + +bool RevisionTree::topDownScan() +{ + m_Data->progress->progressBar()->setTotalSteps(m_Data->max_rev-m_Data->min_rev); + bool cancel=false; + QString label; + QString olabel = m_Data->progress->labelText(); + for (long j=m_Data->max_rev;j>=m_Data->min_rev;--j) { + m_Data->progress->progressBar()->setProgress(m_Data->max_rev-j); + kapp->processEvents(); + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + for (unsigned i = 0; i<m_Data->m_OldHistory[j].changedPaths.count();++i) { + if (i>0 && i%100==0) { + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + label = i18n("%1<br>Check change entry %2 of %3") + .arg(olabel).arg(i).arg(m_Data->m_OldHistory[j].changedPaths.count()); + m_Data->progress->setLabel(label); + kapp->processEvents(); + } + /* find min revision of item */ + if (m_Data->m_OldHistory[j].changedPaths[i].action=='A'&& + isParent(m_Data->m_OldHistory[j].changedPaths[i].path,m_Path)) + { + if (!m_Data->m_OldHistory[j].changedPaths[i].copyFromPath.isEmpty()) { + if (m_InitialRevsion<m_Data->m_OldHistory[j].revision) { + QString tmpPath = m_Path; + QString r = m_Path.mid(m_Data->m_OldHistory[j].changedPaths[i].path.length()); + m_Path=m_Data->m_OldHistory[j].changedPaths[i].copyFromPath; + m_Path+=r; + } + } else if (m_Data->m_OldHistory[j].changedPaths[i].path==m_Path && m_Data->m_OldHistory[j].changedPaths[i].copyToPath.isEmpty()){ + // here it is added + m_InitialRevsion = m_Data->m_OldHistory[j].revision; + } + } + } + } + kdDebug()<<"Stage one done"<<endl; + if (cancel==true) { + return false; + } + m_Data->progress->setLabel(olabel); + /* find forward references and filter them out */ + for (long j=m_Data->max_rev;j>=m_Data->min_rev;--j) { + m_Data->progress->progressBar()->setProgress(m_Data->max_rev-j); + kapp->processEvents(); + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + for (unsigned i = 0; i<m_Data->m_OldHistory[j].changedPaths.count();++i) { + if (i>0 && i%100==0) { + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + label = i18n("%1<br>Check change entry %2 of %3").arg(olabel).arg(i).arg(m_Data->m_OldHistory[j].changedPaths.count()); + m_Data->progress->setLabel(label); + kapp->processEvents(); + } + if (!m_Data->m_OldHistory[j].changedPaths[i].copyFromPath.isEmpty()) { + long r = m_Data->m_OldHistory[j].changedPaths[i].copyFromRevision; + QString sourcepath = m_Data->m_OldHistory[j].changedPaths[i].copyFromPath; + char a = m_Data->m_OldHistory[j].changedPaths[i].action; + if (m_Data->m_OldHistory[j].changedPaths[i].path.isEmpty()) { + kdDebug()<<"Empty entry! rev " << j << " source " << sourcepath << endl; + continue; + } + if (a=='R') { + m_Data->m_OldHistory[j].changedPaths[i].action=0; + } else if (a=='A'){ + a=INTERNALCOPY; + for (unsigned z = 0;z<m_Data->m_OldHistory[j].changedPaths.count();++z) { + if (m_Data->m_OldHistory[j].changedPaths[z].action=='D' + && isParent(m_Data->m_OldHistory[j].changedPaths[z].path,sourcepath) ) { + a=INTERNALRENAME; + m_Data->m_OldHistory[j].changedPaths[z].action=0; + break; + } + } + m_Data->m_History[r].addCopyTo(sourcepath,m_Data->m_OldHistory[j].changedPaths[i].path,j,a,r); + m_Data->m_OldHistory[j].changedPaths[i].action=0; + } else { + kdDebug()<<"Action with source path but wrong action \""<<a<<"\" found!"<<endl; + } + } + } + } + kdDebug()<<"Stage two done"<<endl; + if (cancel==true) { + return false; + } + m_Data->progress->setLabel(olabel); + for (long j=m_Data->max_rev;j>=m_Data->min_rev;--j) { + m_Data->progress->progressBar()->setProgress(m_Data->max_rev-j); + kapp->processEvents(); + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + for (unsigned i = 0; i<m_Data->m_OldHistory[j].changedPaths.count();++i) { + if (m_Data->m_OldHistory[j].changedPaths[i].action==0) { + continue; + } + if (i>0 && i%100==0) { + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + label = i18n("%1<br>Check change entry %2 of %3").arg(olabel).arg(i).arg(m_Data->m_OldHistory[j].changedPaths.count()); + m_Data->progress->setLabel(label); + kapp->processEvents(); + } + m_Data->m_History[j].addCopyTo(m_Data->m_OldHistory[j].changedPaths[i].path,QString::null,-1,m_Data->m_OldHistory[j].changedPaths[i].action); + } + m_Data->m_History[j].author=m_Data->m_OldHistory[j].author; + m_Data->m_History[j].date=m_Data->m_OldHistory[j].date; + m_Data->m_History[j].revision=m_Data->m_OldHistory[j].revision; + m_Data->m_History[j].message=m_Data->m_OldHistory[j].message; + } + kdDebug()<<"Stage three done"<<endl; + return !cancel; +} + +bool RevisionTree::isParent(const QString&_par,const QString&tar) +{ + if (_par==tar) return true; + QString par = _par+(_par.endsWith("/")?"":"/"); + return tar.startsWith(par); +} + +bool RevisionTree::isValid()const +{ + return m_Valid; +} + +static QString uniqueNodeName(long rev,const QString&path) +{ + QString res = KCodecs::base64Encode(path.local8Bit(),false); + res.replace("\"","_quot_"); + res.replace(" ","_space_"); + QString n; n.sprintf("%05ld",rev); + res = "\""+n+QString("_%1\"").arg(res); + return res; +} + +bool RevisionTree::bottomUpScan(long startrev,unsigned recurse,const QString&_path,long _last) +{ +#define REVENTRY m_Data->m_History[j] +#define FORWARDENTRY m_Data->m_History[j].changedPaths[i] + + QString path = _path; + long lastrev = _last; + /* this is required if an item will modified AND copied at same revision.*/ + long trev = -1; +#ifdef DEBUG_PARSE + kdDebug()<<"Searching for "<<path<< " at revision " << startrev + << " recursion " << recurse << endl; +#endif + bool cancel = false; + for (long j=startrev;j<=m_Data->max_rev;++j) { + if (m_Data->m_stopTick.elapsed()>500) { + m_Data->progress->progressBar()->advance(1); + kapp->processEvents(); + m_Data->m_stopTick.restart(); + } + if (m_Data->progress->wasCancelled()) { + cancel=true; + break; + } + for (unsigned i=0;i<REVENTRY.changedPaths.count();++i) { + if (!isParent(FORWARDENTRY.path,path)) { + continue; + } + QString n1,n2; + if (isParent(FORWARDENTRY.path,path)) { + bool get_out = false; + if (FORWARDENTRY.path!=path) { +#ifdef DEBUG_PARSE + kdDebug()<<"Parent rename? "<< FORWARDENTRY.path << " -> " << FORWARDENTRY.copyToPath << " -> " << FORWARDENTRY.copyFromPath << endl; +#endif + } + if (FORWARDENTRY.action==INTERNALCOPY || + FORWARDENTRY.action==INTERNALRENAME ) { + bool ren = FORWARDENTRY.action==INTERNALRENAME; + QString tmpPath = path; + QString recPath; + if (FORWARDENTRY.copyToPath.length()==0) { + continue; + } + QString r = path.mid(FORWARDENTRY.path.length()); + recPath= FORWARDENTRY.copyToPath; + recPath+=r; + n1 = uniqueNodeName(lastrev,tmpPath); + n2 = uniqueNodeName(FORWARDENTRY.copyToRevision,recPath); + if (lastrev>0) { + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n1].targets.append(RevGraphView::targetData(n2,FORWARDENTRY.action)); + } + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].name=recPath; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].rev = FORWARDENTRY.copyToRevision; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Action=FORWARDENTRY.action; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Author=m_Data->m_History[FORWARDENTRY.copyToRevision].author; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Message=m_Data->m_History[FORWARDENTRY.copyToRevision].message; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Date=helpers::sub2qt::apr_time2qtString(m_Data->m_History[FORWARDENTRY.copyToRevision].date); + if (ren) { + lastrev = FORWARDENTRY.copyToRevision; + /* skip items between */ + j=lastrev; +#ifdef DEBUG_PARSE + kdDebug()<<"Renamed to "<< recPath << " at revision " << FORWARDENTRY.copyToRevision << endl; +#endif + path=recPath; + } else { +#ifdef DEBUG_PARSE + kdDebug()<<"Copy to "<< recPath << endl; +#endif + if (!bottomUpScan(FORWARDENTRY.copyToRevision,recurse+1,recPath,FORWARDENTRY.copyToRevision)) { + return false; + } + } + } else if (FORWARDENTRY.path==path) { + switch (FORWARDENTRY.action) { + case 'A': +#ifdef DEBUG_PARSE + kdDebug()<<"Inserting adding base item"<<endl; +#endif + n1 = uniqueNodeName(j,FORWARDENTRY.path); + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n1].Action=FORWARDENTRY.action; + fillItem(j,i,n1,path); + lastrev=j; + break; + case 'M': + case 'R': +#ifdef DEBUG_PARSE + kdDebug()<<"Item modified at revision "<< j << " recurse " << recurse << endl; +#endif + n1 = uniqueNodeName(j,FORWARDENTRY.path); + n2 = uniqueNodeName(lastrev,FORWARDENTRY.path); + if (lastrev>0) m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1,FORWARDENTRY.action)); + fillItem(j,i,n1,path); + /* modify of same item (in same recurse) should be only once at a revision + * so check if lastrev==j must not be done but will cost cpu ticks so I always + * set trev and lastrev. + */ + trev = lastrev; + lastrev = j; + break; + case 'D': +#ifdef DEBUG_PARSE + kdDebug()<<"(Sloppy match) Item deleted at revision "<< j << " recurse " << recurse << endl; +#endif + n1 = uniqueNodeName(j,path); + n2 = uniqueNodeName(lastrev,path); + if (n1==n2) { + /* cvs import - copy and deletion at same revision. + * CVS sucks. + */ + n1 = uniqueNodeName(j,"D_"+path); + } + if (lastrev>0) m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1,FORWARDENTRY.action)); + fillItem(j,i,n1,path); + lastrev = j; + get_out= true; + break; + default: + break; + } + } else { + switch (FORWARDENTRY.action) { + case 'D': +#ifdef DEBUG_PARSE + kdDebug()<<"(Exact match) Item deleted at revision "<< j << " recurse " << recurse << endl; +#endif + n1 = uniqueNodeName(j,path); + n2 = uniqueNodeName(lastrev,path); + if (n1==n2) { + /* cvs import - copy and deletion at same revision. + * CVS sucks. + */ + n1 = uniqueNodeName(j,"D_"+path); + } + if (lastrev>0) m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1,FORWARDENTRY.action)); + fillItem(j,i,n1,path); + lastrev = j; + get_out = true; + break; + default: + break; + } + } + if (get_out) { + return true; + } + } + } + } + return !cancel; +} + +QWidget*RevisionTree::getView() +{ + return m_Data->m_TreeDisplay; +} + +void RevisionTree::fillItem(long rev,int pathIndex,const QString&nodeName,const QString&path) +{ + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].name=path; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].rev = rev; + if (pathIndex>=0) { + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Action=m_Data->m_History[rev].changedPaths[pathIndex].action; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Author=m_Data->m_History[rev].author; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Message=m_Data->m_History[rev].message; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Date=helpers::sub2qt::apr_time2qtString(m_Data->m_History[rev].date); + } else { + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Action=0; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Author=""; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Message=""; + m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Date=helpers::sub2qt::apr_time2qtString(0); + } +} diff --git a/src/svnfrontend/graphtree/revisiontree.h b/src/svnfrontend/graphtree/revisiontree.h new file mode 100644 index 0000000..508306f --- /dev/null +++ b/src/svnfrontend/graphtree/revisiontree.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REVISIONTREE_H +#define REVISIONTREE_H + +#include "src/svnqt/log_entry.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/client.hpp" + +#include <qstring.h> +#include <qmap.h> +#include <qpixmap.h> + +class RtreeData; +class QWidget; +class KListViewItem; +class KListView; +class CContextListener; + +namespace svn +{ + class Client; +} + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class RevisionTree{ +public: + RevisionTree(svn::Client*, + QObject*aListener, + const QString& reposRoot, + const svn::Revision&startr,const svn::Revision&endr, + const QString&,const svn::Revision& baserevision,QWidget*treeParent, + QWidget*parent=0); + virtual ~RevisionTree(); + + bool isValid()const; + QWidget*getView(); + +protected: + long m_Baserevision; + long m_InitialRevsion; + QString m_Path; + bool m_Valid; + + RtreeData*m_Data; + + bool topDownScan(); + bool bottomUpScan(long startrev,unsigned recurse,const QString&path,long sRev = -1); + bool isDeleted(long revision,const QString&); + + static bool isParent(const QString&_par,const QString&tar); + + void fillItem(long revIndex,int pathIndex,const QString&nodeName,const QString&path); +}; + +#endif diff --git a/src/svnfrontend/graphtree/revtreewidget.cpp b/src/svnfrontend/graphtree/revtreewidget.cpp new file mode 100644 index 0000000..35b5258 --- /dev/null +++ b/src/svnfrontend/graphtree/revtreewidget.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "revtreewidget.h" +#include "src/settings/kdesvnsettings.h" + +#include <qvariant.h> +#include <qsplitter.h> +#include <ktextbrowser.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include "revgraphview.h" +#include "ktextbrowser.h" + +/* + * Constructs a RevTreeWidget as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + */ +RevTreeWidget::RevTreeWidget(QObject*lt,svn::Client*cl, QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "RevTreeWidget" ); + RevTreeWidgetLayout = new QVBoxLayout( this, 11, 6, "RevTreeWidgetLayout"); + + m_Splitter = new QSplitter( this, "m_Splitter" ); + m_Splitter->setOrientation( QSplitter::Vertical ); + + m_RevGraphView = new RevGraphView(lt,cl, m_Splitter, "m_RevGraphView" ); + m_RevGraphView->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 0, 2, m_RevGraphView->sizePolicy().hasHeightForWidth() ) ); + connect(m_RevGraphView,SIGNAL(dispDetails(const QString&)),this,SLOT(setDetailText(const QString&))); + connect(m_RevGraphView, + SIGNAL(makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + this, + SIGNAL(makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)) + ); + connect(m_RevGraphView, + SIGNAL(makeRecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + this, + SIGNAL(makeRecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)) + ); + connect(m_RevGraphView, + SIGNAL(makeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*)), + this, + SIGNAL(makeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*)) + ); + + m_Detailstext = new KTextBrowser( m_Splitter, "m_Detailstext" ); + m_Detailstext->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 0, 0, m_Detailstext->sizePolicy().hasHeightForWidth() ) ); + m_Detailstext->setResizePolicy( KTextBrowser::Manual ); + RevTreeWidgetLayout->addWidget( m_Splitter ); + resize( QSize(600, 480).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); + QValueList<int> list = Kdesvnsettings::tree_detail_height(); + if (list.count()==2 && (list[0]>0||list[1]>0)) { + m_Splitter->setSizes(list); + } +} + +/* + * Destroys the object and frees any allocated resources + */ +RevTreeWidget::~RevTreeWidget() +{ + // no need to delete child widgets, Qt does it all for us + QValueList<int> list = m_Splitter->sizes(); + if (list.count()==2) { + Kdesvnsettings::setTree_detail_height(list); + Kdesvnsettings::writeConfig(); + } +} + +void RevTreeWidget::setBasePath(const QString&_p) +{ + m_RevGraphView->setBasePath(_p); +} + +void RevTreeWidget::dumpRevtree() +{ + m_RevGraphView->dumpRevtree(); +} + +void RevTreeWidget::setDetailText(const QString&_s) +{ + m_Detailstext->setText(_s); + QValueList<int> list = m_Splitter->sizes(); + if (list.count()!=2) return; + if (list[1]==0) { + int h = height(); + int th = h/10; + list[0]=h-th; + list[1]=th; + m_Splitter->setSizes(list); + } +} + +#include "revtreewidget.moc" + diff --git a/src/svnfrontend/graphtree/revtreewidget.h b/src/svnfrontend/graphtree/revtreewidget.h new file mode 100644 index 0000000..324f0ba --- /dev/null +++ b/src/svnfrontend/graphtree/revtreewidget.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REVTREEWIDGET_H +#define REVTREEWIDGET_H + +#include <svnqt/revision.hpp> + +#include <qvariant.h> +#include <qpixmap.h> +#include <qwidget.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class RevGraphView; +class QSplitter; +class KTextBrowser; +class CContextListener; + +namespace svn { + class LogEntry; + class Client; +} + +class RevTreeWidget : public QWidget +{ + Q_OBJECT + +public: + RevTreeWidget(QObject*,svn::Client*,QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~RevTreeWidget(); + + QSplitter* m_Splitter; + RevGraphView* m_RevGraphView; + + void setBasePath(const QString&); + void dumpRevtree(); + +protected: + QVBoxLayout* RevTreeWidgetLayout; + KTextBrowser* m_Detailstext; + +signals: + void makeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*); + void makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + void makeRecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + +protected slots: + virtual void setDetailText(const QString&); + +private: + QPixmap image0; + +}; + +#endif // REVTREEWIDGET_H diff --git a/src/svnfrontend/hotcopydlg.ui b/src/svnfrontend/hotcopydlg.ui new file mode 100644 index 0000000..ac0ac7d --- /dev/null +++ b/src/svnfrontend/hotcopydlg.ui @@ -0,0 +1,94 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>HotcopyDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>HotcopyDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>313</width> + <height>156</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_Destlabel</cstring> + </property> + <property name="text"> + <string>Destination folder:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_SrcpathEditor</cstring> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>m_DestpathEditor</cstring> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_Srclabel</cstring> + </property> + <property name="text"> + <string>Repository to copy:</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_Cleanlogs</cstring> + </property> + <property name="text"> + <string>Clean logs</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/hotcopydlg_impl.cpp b/src/svnfrontend/hotcopydlg_impl.cpp new file mode 100644 index 0000000..9211929 --- /dev/null +++ b/src/svnfrontend/hotcopydlg_impl.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "hotcopydlg_impl.h" + +#include <qcheckbox.h> +#include <kurl.h> +#include <kurlrequester.h> + +HotcopyDlg_impl::HotcopyDlg_impl(QWidget *parent, const char *name) + :HotcopyDlg(parent, name) +{ +} + +HotcopyDlg_impl::~HotcopyDlg_impl() +{ +} + +QString HotcopyDlg_impl::srcPath()const +{ + return checkPath(m_SrcpathEditor->url()); +} + +QString HotcopyDlg_impl::destPath()const +{ + return checkPath(m_DestpathEditor->url()); +} + +bool HotcopyDlg_impl::cleanLogs()const +{ + return m_Cleanlogs->isChecked(); +} + +QString HotcopyDlg_impl::checkPath(const QString&_p)const +{ + KURL u = _p; + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + +#include "hotcopydlg_impl.moc" diff --git a/src/svnfrontend/hotcopydlg_impl.h b/src/svnfrontend/hotcopydlg_impl.h new file mode 100644 index 0000000..54655ac --- /dev/null +++ b/src/svnfrontend/hotcopydlg_impl.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef HOTCOPYDLG_IMPL_H +#define HOTCOPYDLG_IMPL_H + +#include "hotcopydlg.h" + +class HotcopyDlg_impl: public HotcopyDlg { +Q_OBJECT +public: + HotcopyDlg_impl(QWidget *parent = 0, const char *name = 0); + virtual ~HotcopyDlg_impl(); + + QString srcPath()const; + QString destPath()const; + bool cleanLogs()const; + +private: + QString checkPath(const QString&)const; + +public slots: + +}; + +#endif diff --git a/src/svnfrontend/importdir_logmsg.cpp b/src/svnfrontend/importdir_logmsg.cpp new file mode 100644 index 0000000..16a6394 --- /dev/null +++ b/src/svnfrontend/importdir_logmsg.cpp @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "importdir_logmsg.h" + +#include "src/svnqt/version_check.hpp" + +#include <klocale.h> + +#include <qcheckbox.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qwhatsthis.h> +#include <qtooltip.h> + + +Importdir_logmsg::Importdir_logmsg(QWidget *parent, const char *name) + : Logmsg_impl(parent, name) +{ + m_createDirBox = new QCheckBox("",this,"create_dir_checkbox"); + m_keepLocksButton->hide(); + //delete m_keepLocksButton; + createDirboxDir(); + addItemWidget(m_createDirBox); + m_createDirBox->setChecked(true); + QHBoxLayout* tmpLayout = new QHBoxLayout( this, 11, 6, "ExtraLayout"); + m_noIgnore = new QCheckBox("",this,"no_ignore_pattern"); + m_noIgnore->setText(i18n("No ignore")); + QToolTip::add(m_noIgnore,i18n("If set, add files or directories that match ignore patterns.")); + tmpLayout->addWidget(m_noIgnore); + //LogmessageDataLayout->addWidget(m_createDirBox); + if (svn::Version::version_major()>1|| svn::Version::version_minor()>4 ) { + m_ignoreUnknownNodes = new QCheckBox("",this,"ignore_unknown_nodes_box"); + m_ignoreUnknownNodes->setText(i18n("Ignore unknown node types")); + QToolTip::add(m_ignoreUnknownNodes,i18n("Should files with unknown node types be ignored")); + QWhatsThis::add(m_ignoreUnknownNodes,i18n("Ignore files of which the node type is unknown, such as device files and pipes.")); + tmpLayout->addWidget(m_ignoreUnknownNodes); + //addItemWidget(m_ignoreUnknownNodes); + } else { + m_ignoreUnknownNodes=0; + } + QSpacerItem* m_leftspacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + tmpLayout->addItem(m_leftspacer); + LogmessageDataLayout->addItem(tmpLayout); +} + +Importdir_logmsg::~Importdir_logmsg() +{ +} + +bool Importdir_logmsg::noIgnore() +{ + return m_noIgnore->isChecked(); +} + +bool Importdir_logmsg::ignoreUnknownNodes() +{ + return m_ignoreUnknownNodes?m_ignoreUnknownNodes->isChecked():false; +} + +bool Importdir_logmsg::createDir() +{ + return m_createDirBox->isChecked(); +} + +void Importdir_logmsg::createDirboxDir(const QString & which) +{ + m_createDirBox->setText(i18n("Create subdir %1 on import").arg(which.isEmpty()?i18n("(Last part)"):which)); +} + +#include "importdir_logmsg.moc" diff --git a/src/svnfrontend/importdir_logmsg.h b/src/svnfrontend/importdir_logmsg.h new file mode 100644 index 0000000..8a7aacb --- /dev/null +++ b/src/svnfrontend/importdir_logmsg.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef IMPORTDIR_LOGMSG_H +#define IMPORTDIR_LOGMSG_H + +#include "src/ksvnwidgets/logmsg_impl.h" + +class QCheckBox; +/** +@author Rajko Albrecht +*/ +class Importdir_logmsg : public Logmsg_impl +{ +Q_OBJECT +public: + Importdir_logmsg(QWidget *parent = 0, const char *name = 0); + + virtual ~Importdir_logmsg(); + + bool createDir(); + bool ignoreUnknownNodes(); + bool noIgnore(); + void createDirboxDir(const QString & which=QString::null); + +protected: + QCheckBox*m_createDirBox; + QCheckBox*m_ignoreUnknownNodes; + QCheckBox*m_noIgnore; +}; + +#endif diff --git a/src/svnfrontend/itemdisplay.cpp b/src/svnfrontend/itemdisplay.cpp new file mode 100644 index 0000000..6a675ed --- /dev/null +++ b/src/svnfrontend/itemdisplay.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "itemdisplay.h" +#include "svnitem.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/status.hpp" + + +ItemDisplay::ItemDisplay() + :m_LastException(""),m_isWorkingCopy(false),m_isNetworked(false),m_baseUri("") +{ +} + +bool ItemDisplay::isWorkingCopy()const +{ + return m_isWorkingCopy; +} + +const QString&ItemDisplay::baseUri()const +{ + return m_baseUri; +} + +/*! + \fn ItemDisplay::isNetworked()const + */ +bool ItemDisplay::isNetworked()const +{ + return m_isNetworked; +} + +void ItemDisplay::setWorkingCopy(bool how) +{ + m_isWorkingCopy=how; +} + +void ItemDisplay::setNetworked(bool how) +{ + m_isNetworked=how; +} + +void ItemDisplay::setBaseUri(const QString&uri) +{ + m_baseUri = uri; + /* otherwise subversion lib asserts! */ + while (m_baseUri.endsWith("/")) { + m_baseUri.truncate(m_baseUri.length()-1); + } +} + +const QString&ItemDisplay::lastError()const +{ + return m_LastException; +} + + +/*! + \fn ItemDisplay::filterOut(const SvnItem*) + */ +bool ItemDisplay::filterOut(const SvnItem*item) +{ + return filterOut(item->stat()); +} + + +/*! + \fn ItemDisplay::filterOut(const svn::Status&) + */ +bool ItemDisplay::filterOut(const svn::StatusPtr&item) +{ + bool res = false; + + if (!item->validReposStatus()) { + if ((!Kdesvnsettings::display_unknown_files() && !item->isVersioned()) || + (Kdesvnsettings::hide_unchanged_files() && item->isRealVersioned() && !item->isModified() && !item->entry().isDir())) { + res = true; + } + } + return res; +} + + +/*! + \fn ItemDisplay::relativePath(const SvnItem*item) + */ +QString ItemDisplay::relativePath(const SvnItem*item) +{ + if (!isWorkingCopy()||!item->fullName().startsWith(baseUri())) { + return item->fullName(); + } + QString name = item->fullName(); + if (name==baseUri()) { + name = "."; + } else { + name = name.right(name.length()-baseUri().length()-1); + } + if (name.isEmpty()) { + name = "."; + } + return name; +} diff --git a/src/svnfrontend/itemdisplay.h b/src/svnfrontend/itemdisplay.h new file mode 100644 index 0000000..b487904 --- /dev/null +++ b/src/svnfrontend/itemdisplay.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef __ITEMDISPLAY_H +#define __ITEMDISPLAY_H + +#include "src/svnqt/svnqttypes.hpp" +#include <qptrlist.h> +#include <qstring.h> +#include <kurl.h> + +class QWidget; + +class SvnItem; + +namespace svn +{ + class Status; +} + +class ItemDisplay +{ +public: + ItemDisplay(); + virtual ~ItemDisplay(){} + virtual bool isWorkingCopy()const; + virtual QWidget*realWidget() = 0; + virtual SvnItem*Selected()=0; + virtual void SelectionList(QPtrList<SvnItem>*)=0; + virtual const QString&baseUri()const; + virtual bool openURL( const KURL &url,bool noReinit=false )=0; + virtual SvnItem*SelectedOrMain()=0; + virtual bool isNetworked()const; + virtual const QString&lastError()const; + virtual bool filterOut(const SvnItem*); + virtual bool filterOut(const svn::StatusPtr&); + QString relativePath(const SvnItem*item); + +protected: + void setWorkingCopy(bool); + void setNetworked(bool); + void setBaseUri(const QString&); + QString m_LastException; + +private: + bool m_isWorkingCopy; + bool m_isNetworked; + QString m_baseUri; +}; + +#endif diff --git a/src/svnfrontend/kdesvnfilelist.cpp b/src/svnfrontend/kdesvnfilelist.cpp new file mode 100644 index 0000000..d9116cb --- /dev/null +++ b/src/svnfrontend/kdesvnfilelist.cpp @@ -0,0 +1,3160 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "kdesvnfilelist.h" +#include "kdesvn_part.h" +#include "filelistviewitem.h" +#include "importdir_logmsg.h" +#include "copymoveview_impl.h" +#include "mergedlg_impl.h" +#include "svnactions.h" +#include "svnfiletip.h" +#include "keystatus.h" +#include "opencontextmenu.h" +#include "checkoutinfo_impl.h" +#include "stopdlg.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/dirent.hpp" +#include "src/svnqt/client.hpp" +#include "src/svnqt/status.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/sshagent.h" +#include "helpers/sub2qt.h" +#include "fronthelpers/cursorstack.h" +#include "fronthelpers/widgetblockstack.h" + +#include <kapplication.h> +#include <kiconloader.h> +#include <kdirwatch.h> +#include <klocale.h> +#include <kactioncollection.h> +#include <kshortcut.h> +#include <kmessagebox.h> +#include <kdirselectdialog.h> +#include <klineedit.h> +#include <kfileitem.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kdebug.h> +#include <kurldrag.h> +#include <ktempfile.h> +#include <kio/job.h> +#include <krun.h> +#include <kurldrag.h> +#include <ktrader.h> + +#include <qvbox.h> +#include <qpainter.h> +#include <qstyle.h> +#include <qapplication.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qregexp.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qheader.h> +#include <qcheckbox.h> + +#include <unistd.h> + +class KdesvnFileListPrivate{ +public: + KdesvnFileListPrivate(); + virtual ~KdesvnFileListPrivate() + { + if (m_DirWatch) { + m_DirWatch->stopScan(); + delete m_DirWatch; + } + delete m_fileTip; + kdDebug()<<"Destructor KdesvnFileListPrivate done"<<endl; + }; + QListViewItem *dragOverItem; + QPoint dragOverPoint; + QRect mOldDropHighlighter; + svn::Revision m_remoteRevision; + KDirWatch*m_DirWatch; + SvnFileTip*m_fileTip; + int mlist_icon_size; + bool mdisp_ignored_files; + bool mdisp_unknown_files; + bool mdisp_overlay; + /* returns true if the display must refreshed */ + bool reReadSettings(); + + bool intern_dropRunning; + KURL::List intern_drops; + QString intern_drop_target,merge_Src1, merge_Src2,merge_Target; + QDropEvent::Action intern_drop_action; + QPoint intern_drop_pos; + QTimer drop_timer; + QTimer dirwatch_timer; + QTimer propTimer; + + bool mousePressed; + QPoint presspos; + + QMap<QString,QChar> dirItems; + + void stopDirTimer() + { + dirwatch_timer.stop(); + } + + void startDirTimer() + { + dirwatch_timer.start(250,true); + } + + void connectDirTimer(QObject*ob) + { + QObject::connect(&dirwatch_timer,SIGNAL(timeout()),ob,SLOT(_dirwatchTimeout())); + } + void stopScan() + { + if (m_DirWatch) { + m_DirWatch->stopScan(); + } + } + void startScan() + { + if (m_DirWatch) { + m_DirWatch->startScan(); + } + } + void startProptimer() + { + propTimer.start(100,true); + } + void stopProptimer() + { + propTimer.stop(); + } + void connectPropTimer(QObject*ob) + { + QObject::connect(&propTimer,SIGNAL(timeout()),ob,SLOT(_propListTimeout())); + } + +private: + void readSettings(); +}; + +KdesvnFileListPrivate::KdesvnFileListPrivate() + : dragOverItem(0),dragOverPoint(QPoint(0,0)),mOldDropHighlighter() +{ + m_remoteRevision = svn::Revision::HEAD; + m_DirWatch = 0; + intern_dropRunning=false; + mousePressed = false; + readSettings(); +} + +void KdesvnFileListPrivate::readSettings() +{ + mlist_icon_size = Kdesvnsettings::listview_icon_size(); + mdisp_ignored_files = Kdesvnsettings::display_ignored_files(); + mdisp_unknown_files = Kdesvnsettings::display_unknown_files(); + mdisp_overlay = Kdesvnsettings::display_overlays(); +} + +bool KdesvnFileListPrivate::reReadSettings() +{ + int _size = mlist_icon_size; + bool _ignored = mdisp_ignored_files; + bool _overlay = mdisp_overlay; + bool _unknown = mdisp_unknown_files; + readSettings(); + return (_size != mlist_icon_size|| + _ignored!=mdisp_ignored_files|| + _overlay!=mdisp_overlay|| + _unknown != mdisp_unknown_files); +} + +kdesvnfilelist::kdesvnfilelist(KActionCollection*aCollect,QWidget *parent, const char *name) + : KListView(parent, name),ItemDisplay(),m_SvnWrapper(new SvnActions(this)) +{ + m_SelectedItems = 0; + m_pList = new KdesvnFileListPrivate; + m_filesAction = aCollect; + m_pList->m_fileTip=new SvnFileTip(this); + m_pList->m_fileTip->setOptions(Kdesvnsettings::display_file_tips()&& + QToolTip::isGloballyEnabled(),true,6); + + SshAgent ssh; + ssh.querySshAgent(); + + setMultiSelection(true); + setSelectionModeExt(FileManager); + setShowSortIndicator(true); + setAllColumnsShowFocus (true); + setRootIsDecorated(true); + addColumn(i18n("Name")); + addColumn(i18n("Status")); + addColumn(i18n("Last changed Revision")); + addColumn(i18n("Last author")); + addColumn(i18n("Last change date")); + addColumn(i18n("Locked by")); + setSortColumn(FileListViewItem::COL_NAME); + setupActions(); + + connect(this,SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),this, + SLOT(slotContextMenuRequested(QListViewItem *, const QPoint &, int))); + + /* not via executed 'cause click may used for selection - single click execution + just confuses in an application */ + connect(this,SIGNAL(doubleClicked(QListViewItem*)),this,SLOT(slotItemDoubleClicked(QListViewItem*))); + connect(this,SIGNAL(returnPressed(QListViewItem*)),this,SLOT(slotItemDoubleClicked(QListViewItem*))); + + connect(this,SIGNAL(selectionChanged()),this,SLOT(slotSelectionChanged())); + connect(m_SvnWrapper,SIGNAL(clientException(const QString&)),this,SLOT(slotClientException(const QString&))); + connect(m_SvnWrapper,SIGNAL(sendNotify(const QString&)),this,SLOT(slotNotifyMessage(const QString&))); + connect(m_SvnWrapper,SIGNAL(reinitItem(SvnItem*)),this,SLOT(slotReinitItem(SvnItem*))); + connect(m_SvnWrapper,SIGNAL(sigRefreshAll()),this,SLOT(refreshCurrentTree())); + connect(m_SvnWrapper,SIGNAL(sigRefreshCurrent(SvnItem*)),this,SLOT(refreshCurrent(SvnItem*))); + connect(m_SvnWrapper,SIGNAL(sigRefreshIcons(bool)),this,SLOT(slotRescanIcons(bool))); + connect(this,SIGNAL(dropped (QDropEvent*,QListViewItem*)), + this,SLOT(slotDropped(QDropEvent*,QListViewItem*))); + connect(m_SvnWrapper,SIGNAL(sigGotourl(const QString&)),this,SLOT(_openURL(const QString&))); + + connect(m_SvnWrapper,SIGNAL(sigCacheStatus(Q_LONG,Q_LONG)),this,SIGNAL(sigCacheStatus(Q_LONG,Q_LONG))); + connect(m_SvnWrapper,SIGNAL(sigThreadsChanged()),this,SLOT(enableActions())); + + m_pList->connectDirTimer(this); + m_pList->connectPropTimer(this); + + setDropHighlighter(true); + setDragEnabled(true); + setItemsMovable(true); + setDropVisualizer(false); + setAcceptDrops(true); +} + +svn::Client*kdesvnfilelist::svnclient() +{ + return m_SvnWrapper->svnclient(); +} + +void kdesvnfilelist::setupActions() +{ + if (!m_filesAction) return; + KAction*tmp_action; + /* local and remote actions */ + /* 1. actions on dirs AND files */ + //new KAction(i18n("Log..."),"kdesvnlog",KShortcut(SHIFT+CTRL+Key_L),this,SLOT(slotMakeRangeLog()),m_filesAction,"make_svn_log"); + new KAction(i18n("Full Log"),"kdesvnlog",KShortcut(CTRL+Key_L),this,SLOT(slotMakeLog()),m_filesAction,"make_svn_log_full"); + new KAction(i18n("Full revision tree"),"kdesvnlog",KShortcut(CTRL+Key_T),this,SLOT(slotMakeTree()),m_filesAction,"make_svn_tree"); + new KAction(i18n("Partial revision tree"),"kdesvnlog",KShortcut(SHIFT+CTRL+Key_T), + this,SLOT(slotMakePartTree()),m_filesAction,"make_svn_partialtree"); + + new KAction(i18n("Properties"),"edit", + KShortcut(CTRL+Key_P),m_SvnWrapper,SLOT(slotProperties()),m_filesAction,"make_svn_property"); + new KAction(i18n("Display Properties"),"edit", + KShortcut(SHIFT+CTRL+Key_P),this,SLOT(slotDisplayProperties()),m_filesAction,"get_svn_property"); + + tmp_action = new KAction(i18n("Display last changes"),"kdesvndiff", + KShortcut(),this,SLOT(slotDisplayLastDiff()),m_filesAction,"make_last_change"); + tmp_action->setToolTip(i18n("Display last changes as difference to previous commit.")); + + m_InfoAction = new KAction(i18n("Details"),"kdesvninfo", + KShortcut(CTRL+Key_I),this,SLOT(slotInfo()),m_filesAction,"make_svn_info"); + m_RenameAction = new KAction(i18n("Move"),"move", + KShortcut(Key_F2),this,SLOT(slotRename()),m_filesAction,"make_svn_rename"); + m_CopyAction = new KAction(i18n("Copy"),"kdesvncopy", + KShortcut(CTRL+Key_C),this,SLOT(slotCopy()),m_filesAction,"make_svn_copy"); + tmp_action = new KAction(i18n("Check for updates"),"kdesvncheckupdates",KShortcut(),this,SLOT(slotCheckUpdates()),m_filesAction,"make_check_updates"); + tmp_action->setToolTip(i18n("Check if current working copy has items with newer version in repository")); + + /* 2. actions only on files */ + m_BlameAction = new KAction(i18n("Blame"),"kdesvnblame", + KShortcut(),this,SLOT(slotBlame()),m_filesAction,"make_svn_blame"); + m_BlameAction->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line.")); + m_BlameRangeAction = new KAction(i18n("Blame range"),"kdesvnblame", + KShortcut(),this,SLOT(slotRangeBlame()),m_filesAction,"make_svn_range_blame"); + m_BlameRangeAction->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line.")); + m_CatAction = new KAction(i18n("Cat head"), "kdesvncat", + KShortcut(),this,SLOT(slotCat()),m_filesAction,"make_svn_cat"); + m_CatAction->setToolTip(i18n("Output the content of specified files or URLs.")); + tmp_action = new KAction(i18n("Cat revision..."),"kdesvncat", + KShortcut(),this,SLOT(slotRevisionCat()),m_filesAction,"make_revisions_cat"); + tmp_action->setToolTip(i18n("Output the content of specified files or URLs at specific revision.")); + + m_LockAction = new KAction(i18n("Lock current items"),"kdesvnlock", + KShortcut(),this,SLOT(slotLock()),m_filesAction,"make_svn_lock"); + m_UnlockAction = new KAction(i18n("Unlock current items"),"kdesvnunlock", + KShortcut(),this,SLOT(slotUnlock()),m_filesAction,"make_svn_unlock"); + + /* 3. actions only on dirs */ + m_MkdirAction = new KAction(i18n("New folder"),"folder_new", + KShortcut(),this,SLOT(slotMkdir()),m_filesAction,"make_svn_mkdir"); + m_switchRepository = new KAction(i18n("Switch repository"),"kdesvnswitch", + KShortcut(), m_SvnWrapper,SLOT(slotSwitch()),m_filesAction,"make_svn_switch"); + m_switchRepository->setToolTip(i18n("Switch repository path of current working copy path (\"svn switch\")")); + tmp_action = new KAction(i18n("Relocate current working copy url"),"kdesvnrelocate",KShortcut(), + this,SLOT(slotRelocate()),m_filesAction,"make_svn_relocate"); + tmp_action->setToolTip(i18n("Relocate url of current working copy path to other url")); + tmp_action = new KAction(i18n("Check for unversioned items"),"kdesvnaddrecursive",KShortcut(), + this,SLOT(slotCheckNewItems()),m_filesAction,"make_check_unversioned"); + tmp_action->setToolTip(i18n("Browse folder for unversioned items and add them if wanted.")); + + m_changeToRepository = new KAction(i18n("Open repository of working copy"),"gohome",KShortcut(), + this,SLOT(slotChangeToRepository()),m_filesAction,"make_switch_to_repo"); + m_changeToRepository->setToolTip(i18n("Opens the repository the current working copy was checked out from")); + + m_CleanupAction = new KAction(i18n("Cleanup"),"kdesvncleanup", + KShortcut(),this,SLOT(slotCleanupAction()),m_filesAction,"make_cleanup"); + m_CleanupAction->setToolTip(i18n("Recursively clean up the working copy, removing locks, resuming unfinished operations, etc.")); + m_ImportDirsIntoCurrent = new KAction(i18n("Import folders into current"),"fileimport",KShortcut(), + this,SLOT(slotImportDirsIntoCurrent()),m_filesAction,"make_import_dirs_into_current"); + m_ImportDirsIntoCurrent->setToolTip(i18n("Import folder content into current url")); + + /* local only actions */ + /* 1. actions on files AND dirs*/ + m_AddCurrent = new KAction(i18n("Add selected files/dirs"), + "kdesvnadd",KShortcut(Key_Insert),m_SvnWrapper,SLOT(slotAdd()),m_filesAction,"make_svn_add"); + m_AddCurrent->setToolTip(i18n("Adding selected files and/or directories to repository")); + tmp_action = new KAction("Add selected files/dirs recursive", + "kdesvnaddrecursive",KShortcut(CTRL+Key_Insert),m_SvnWrapper,SLOT(slotAddRec()),m_filesAction,"make_svn_addrec"); + tmp_action->setToolTip(i18n("Adding selected files and/or directories to repository and all subitems of folders")); + + m_DelCurrent = new KAction(i18n("Delete selected files/dirs"),"kdesvndelete", + KShortcut(Key_Delete),this,SLOT(slotDelete()),m_filesAction,"make_svn_remove"); + m_DelCurrent->setToolTip(i18n("Deleting selected files and/or directories from repository")); + m_RevertAction = new KAction(i18n("Revert current changes"),"revert", + KShortcut(),m_SvnWrapper,SLOT(slotRevert()),m_filesAction,"make_svn_revert"); + + m_ResolvedAction = new KAction(i18n("Mark resolved"),KShortcut(), + this,SLOT(slotResolved()),m_filesAction,"make_resolved"); + m_ResolvedAction->setToolTip(i18n("Marking files or dirs resolved")); + + tmp_action = new KAction(i18n("Resolve conflicts"),KShortcut(), + this,SLOT(slotTryResolve()),m_filesAction,"make_try_resolve"); + + m_IgnoreAction = new KAction(i18n("Ignore/Unignore current item"),KShortcut(),this,SLOT(slotIgnore()),m_filesAction,"make_svn_ignore"); + + m_UpdateHead = new KAction(i18n("Update to head"),"kdesvnupdate", + KShortcut(),m_SvnWrapper,SLOT(slotUpdateHeadRec()),m_filesAction,"make_svn_headupdate"); + m_UpdateRev = new KAction(i18n("Update to revision..."),"kdesvnupdate", + KShortcut(),m_SvnWrapper,SLOT(slotUpdateTo()),m_filesAction,"make_svn_revupdate"); + m_commitAction = new KAction(i18n("Commit"),"kdesvncommit", + KShortcut("CTRL+#"),m_SvnWrapper,SLOT(slotCommit()),m_filesAction,"make_svn_commit"); + + tmp_action = new KAction(i18n("Diff local changes"),"kdesvndiff", + KShortcut(CTRL+Key_D),this,SLOT(slotSimpleBaseDiff()),m_filesAction,"make_svn_basediff"); + tmp_action->setToolTip(i18n("Diff working copy against BASE (last checked out version) - doesn't require access to repository")); + + tmp_action = new KAction(i18n("Diff against HEAD"),"kdesvndiff", + KShortcut(CTRL+Key_H),this,SLOT(slotSimpleHeadDiff()),m_filesAction,"make_svn_headdiff"); + tmp_action->setToolTip(i18n("Diff working copy against HEAD (last checked in version)- requires access to repository")); + + tmp_action = new KAction(i18n("Diff items"),"kdesvndiff", + KShortcut(),this,SLOT(slotDiffPathes()),m_filesAction,"make_svn_itemsdiff"); + tmp_action->setToolTip(i18n("Diff two items")); + + + m_MergeRevisionAction = new KAction(i18n("Merge two revisions"),"kdesvnmerge", + KShortcut(),this,SLOT(slotMergeRevisions()),m_filesAction,"make_svn_merge_revisions"); + m_MergeRevisionAction->setToolTip(i18n("Merge two revisions of this entry into itself")); + + tmp_action=new KAction(i18n("Merge..."),"kdesvnmerge", + KShortcut(),this,SLOT(slotMerge()),m_filesAction,"make_svn_merge"); + tmp_action->setToolTip("Merge repository path into current worky copy path or current repository path into a target"); + tmp_action=new KAction( i18n( "Open With..." ), 0, this, SLOT( slotOpenWith() ), m_filesAction, "openwith" ); + + /* remote actions only */ + m_CheckoutCurrentAction = new KAction(i18n("Checkout current repository path"),"kdesvncheckout",KShortcut(), + m_SvnWrapper,SLOT(slotCheckoutCurrent()),m_filesAction,"make_svn_checkout_current"); + m_ExportCurrentAction = new KAction(i18n("Export current repository path"),"kdesvnexport",KShortcut(), + m_SvnWrapper,SLOT(slotExportCurrent()),m_filesAction,"make_svn_export_current"); + new KAction(i18n("Select browse revision"),KShortcut(),this,SLOT(slotSelectBrowsingRevision()),m_filesAction,"switch_browse_revision"); + + /* independe actions */ + m_CheckoutAction = new KAction(i18n("Checkout a repository"),"kdesvncheckout", + KShortcut(),m_SvnWrapper,SLOT(slotCheckout()),m_filesAction,"make_svn_checkout"); + m_ExportAction = new KAction(i18n("Export a repository"),"kdesvnexport", + KShortcut(),m_SvnWrapper,SLOT(slotExport()),m_filesAction,"make_svn_export"); + m_RefreshViewAction = new KAction(i18n("Refresh view"),"reload",KShortcut(Key_F5),this,SLOT(refreshCurrentTree()),m_filesAction,"make_view_refresh"); + + new KAction(i18n("Diff revisions"),"kdesvndiff",KShortcut(),this,SLOT(slotDiffRevisions()),m_filesAction,"make_revisions_diff"); + + /* folding options */ + tmp_action = new KAction( i18n("Unfold File Tree"), 0, this , SLOT(slotUnfoldTree()), m_filesAction, "view_unfold_tree" ); + tmp_action->setToolTip(i18n("Opens all branches of the file tree")); + tmp_action = new KAction( i18n("Fold File Tree"), 0, this, SLOT(slotFoldTree()), m_filesAction, "view_fold_tree" ); + tmp_action->setToolTip(i18n("Closes all branches of the file tree")); + + /* caching */ + tmp_action = new KAction( i18n("Update log cache"),0,this,SLOT(slotUpdateLogCache()),m_filesAction,"update_log_cache" ); + tmp_action->setToolTip(i18n("Update the log cache for current repository")); + /* tmp_action = new KAction( i18n("Stop update log cache"),0,this,SLOT(slotUpdateLogCache()),m_filesAction,"stop_update_log_cache" ); + tmp_action->setToolTip(i18n("Stop the update of the log cache")); + */ + + enableActions(); + m_filesAction->setHighlightingEnabled(true); +} + +KActionCollection*kdesvnfilelist::filesActions() +{ + return m_filesAction; +} + +FileListViewItemList* kdesvnfilelist::allSelected() +{ + if (!m_SelectedItems) { + m_SelectedItems = new FileListViewItemList; + } + return m_SelectedItems; +} + +void kdesvnfilelist::SelectionList(SvnItemList*target) +{ + if (!m_SelectedItems||!target) return; + FileListViewItemListIterator iter(*m_SelectedItems); + FileListViewItem*cur; + while ( (cur=iter.current())!=0) { + ++iter; + target->append(cur); + } +} + +SvnItem*kdesvnfilelist::SelectedOrMain() +{ + if (singleSelected()!=0) { + return singleSelected(); + } + if (isWorkingCopy()&&firstChild()) { + return static_cast<FileListViewItem*>(firstChild()); + } + return 0; +} + +KURL::List kdesvnfilelist::selectedUrls() +{ + KURL::List lst; + FileListViewItemList*ls = allSelected(); + FileListViewItemListIterator it(*ls); + FileListViewItem*cur; + while ( (cur=it.current())!=0) { + ++it; + /* for putting it to outside we must convert it to KIO urls */ + lst.append(cur->kdeName(m_pList->m_remoteRevision)); + } + return lst; +} + +QWidget*kdesvnfilelist::realWidget() +{ + return this; +} + +FileListViewItem* kdesvnfilelist::singleSelected() +{ + if (m_SelectedItems && m_SelectedItems->count()==1) { + return m_SelectedItems->at(0); + } + return 0; +} + +SvnItem*kdesvnfilelist::Selected() +{ + return singleSelected(); +} + +void kdesvnfilelist::_openURL(const QString&url) +{ + openURL(url,true); + emit sigUrlChanged(baseUri()); +} + +bool kdesvnfilelist::openURL( const KURL &url,bool noReinit ) +{ + CursorStack a; + m_SvnWrapper->killallThreads(); + clear(); + emit sigProplist(svn::PathPropertiesMapListPtr(new svn::PathPropertiesMapList()),false,QString("")); + m_Dirsread.clear(); + if (m_SelectedItems) { + m_SelectedItems->clear(); + } + m_LastException=""; + delete m_pList->m_DirWatch; + m_pList->m_DirWatch=0; + m_pList->dirItems.clear(); + m_pList->stopDirTimer(); + + if (!noReinit) m_SvnWrapper->reInitClient(); + + QString query = url.query(); + + KURL _url = url; + QString proto = svn::Url::transformProtokoll(url.protocol()); + _url.cleanPath(true); + _url.setProtocol(proto); + proto = _url.url(-1); + + QStringList s = QStringList::split("?",proto); + if (s.size()>1) { + setBaseUri(s[0]); + } else { + setBaseUri(proto); + } + setWorkingCopy(false); + setNetworked(false); + + m_pList->m_remoteRevision=svn::Revision::HEAD; + + + QString _dummy; + + if (!QString::compare("svn+file",url.protocol())) { + setBaseUri("file://"+url.path()); + } else { + if (url.isLocalFile()) { + QString s = url.path(); + while(s.endsWith("/")) { + s.remove(s.length()-1,1); + } + QFileInfo fi(s); + if (fi.exists() && fi.isSymLink()) { + QString sl = fi.readLink(); + if (sl.startsWith("/")) { + setBaseUri(sl); + } else { + fi.setFile(fi.dirPath()+"/"+sl); + setBaseUri(fi.absFilePath()); + } + } else { + setBaseUri(url.path()); + } + if (m_SvnWrapper->isLocalWorkingCopy(baseUri(),_dummy)) { + setWorkingCopy(true); + } else { + // yes! KURL sometimes makes a correct localfile url (file:///) + // to a simple file:/ - that breakes subversion lib. so we make sure + // that we have a correct url + setBaseUri("file://"+baseUri()); + } + } else { + setNetworked(true); + if (!Kdesvnsettings::network_on()) { + setBaseUri(""); + setNetworked(false); + clear(); + KMessageBox::error(this,i18n("Networked URL to open but networking is disabled!")); + emit changeCaption(""); + emit sigUrlOpend(false); + return false; + } + } + } + if (query.length()>1) { + QMap<QString,QString> q = url.queryItems(); + if (q.find("rev")!=q.end()) { + QString v = q["rev"]; + svn::Revision tmp; + m_SvnWrapper->svnclient()->url2Revision(v,m_pList->m_remoteRevision,tmp); + if (m_pList->m_remoteRevision==svn::Revision::UNDEFINED) { + m_pList->m_remoteRevision = svn::Revision::HEAD; + } + } + } + + if (url.protocol()=="svn+ssh"|| + url.protocol()=="ksvn+ssh") { + SshAgent ssh; + ssh.addSshIdentities(); + } + m_SvnWrapper->clearUpdateCache(); + if (isWorkingCopy()) { + m_pList->m_DirWatch=new KDirWatch(this); + connect(m_pList->m_DirWatch,SIGNAL(dirty(const QString&)),this,SLOT(slotDirItemDirty(const QString&))); + connect(m_pList->m_DirWatch,SIGNAL(created(const QString&)),this,SLOT(slotDirItemCreated(const QString&))); + connect(m_pList->m_DirWatch,SIGNAL(deleted(const QString&)),this,SLOT(slotDirItemDeleted(const QString&))); + /* seems that recursive does not work */ + if (m_pList->m_DirWatch) { + m_pList->m_DirWatch->addDir(baseUri()+"/",false,false); + m_pList->m_DirWatch->startScan(true); + } + } + bool result = checkDirs(baseUri(),0); + if (result && isWorkingCopy()) { + chdir(baseUri().local8Bit()); + if (firstChild()) firstChild()->setOpen(true); + } + if (!result) { + setBaseUri(""); + setNetworked(false); + clear(); + } + m_pList->m_fileTip->setOptions(!isNetworked()&&Kdesvnsettings::display_file_tips()&& + QToolTip::isGloballyEnabled(),true,6); + + if (result && isWorkingCopy()) { + m_SvnWrapper->createModifiedCache(baseUri()); + if (Kdesvnsettings::start_updates_check_on_open()) { + slotCheckUpdates(); + } + } + if (Kdesvnsettings::log_cache_on_open()) { + kdDebug()<<"Starting logcache"<<endl; + m_SvnWrapper->startFillCache(baseUri()); + } + emit changeCaption(baseUri()); + emit sigUrlOpend(result); + QTimer::singleShot(1,this,SLOT(readSupportData())); + enableActions(); + return result; +} + +void kdesvnfilelist::closeMe() +{ + m_SvnWrapper->killallThreads(); + + selectAll(false); + clear(); + setWorkingCopy(""); + setNetworked(false); + setWorkingCopy(false); + setBaseUri(""); + + emit changeCaption(""); + emit sigUrlOpend(false); + + enableActions(); + m_SvnWrapper->reInitClient(); + delete m_pList->m_DirWatch; + m_pList->m_DirWatch = 0; + m_pList->m_fileTip->setItem(0); +} + +bool kdesvnfilelist::checkDirs(const QString&_what,FileListViewItem * _parent) +{ + QString what = _what; + svn::StatusEntries dlist; + while (what.endsWith("/")) { + what.truncate(what.length()-1); + } + // prevent this from checking unversioned folder. FIXME: what happen when we do open url on a non-working-copy folder?? + if (!isWorkingCopy()|| (!_parent) || ((_parent) && (_parent->isVersioned()))) { + if (!m_SvnWrapper->makeStatus(what,dlist,m_pList->m_remoteRevision) ) { + kdDebug() << "unable makeStatus" <<endl; + return false; + } + } else { + checkUnversionedDirs(_parent); + return true; + } + svn::StatusEntries neweritems; + m_SvnWrapper->getaddedItems(what,neweritems); + dlist+=neweritems; + bool ownupdates = true; + //kdDebug() << "makeStatus on " << what << " created: " << dlist.count() << "items" <<endl; + + if (isUpdatesEnabled()) { + viewport()->setUpdatesEnabled(false); + } else { + ownupdates=false; + } + svn::StatusEntries::iterator it = dlist.begin(); + FileListViewItem * pitem = 0; + bool main_found = false; + for (;it!=dlist.end();++it) { + //kdDebug() << "iterate over it: " << (*it)->entry().url() << endl; + + // current item is not versioned + if (!(*it)->isVersioned() && !filterOut((*it))) { + // if empty, we may want to create a default svn::Status for each folder inside this _parent + // iterate over QDir and create new filelistviewitem + checkUnversionedDirs(_parent); + } + + if ((*it)->path()==what||QString::compare((*it)->entry().url(),what)==0){ + if (!_parent) { + pitem = new FileListViewItem(this,*it); + //kdDebug()<< "CheckDirs::creating new FileListViewitem as parent " + (*it)->path() << endl; + m_Dirsread[pitem->fullName()]=true; + pitem->setDropEnabled(true); + } + dlist.erase(it); + main_found = true; + break; + } + } + if (_parent) { + pitem = _parent; + } + insertDirs(pitem,dlist); + if (ownupdates) { + kdDebug()<<"Enable update"<<endl; + viewport()->setUpdatesEnabled(true); + viewport()->repaint(); + } + return true; +} + +void kdesvnfilelist::insertDirs(FileListViewItem * _parent,svn::StatusEntries&dlist) +{ + svn::StatusEntries::iterator it; +#if 0 + KFileItemList oneItem; +#endif + + QTime _t; + _t.start(); + for (it = dlist.begin();it!=dlist.end();++it) { +/* if (_t.elapsed()>300) { + viewport()->setUpdatesEnabled(true); + viewport()->repaint(); + viewport()->setUpdatesEnabled(false); + _t.restart(); + }*/ + if (filterOut((*it))) + { + continue; + } + FileListViewItem * item; + if (!_parent) { + item = new FileListViewItem(this,*it); + } else { + if ( (item = _parent->findChild( (*it)->path() )) ) { + delete item; + } + item = new FileListViewItem(this,_parent,*it); + } + if (item->isDir()) { + m_Dirsread[item->fullName()]=false; + item->setDropEnabled(true); + if (isWorkingCopy()) { + m_pList->m_DirWatch->addDir(item->fullName()); + } + } else if (isWorkingCopy()) { + m_pList->m_DirWatch->addFile(item->fullName()); + } + } +} + +/* newdir is the NEW directory! just required if local */ +void kdesvnfilelist::slotDirAdded(const QString&newdir,FileListViewItem*k) +{ + if (k) { + k->refreshStatus(); + } + if (!isWorkingCopy()) { + if (k) { + k->removeChilds(); + m_Dirsread[k->fullName()]=false; + if (checkDirs(k->fullName(),k)) { + m_Dirsread[k->fullName()]=true; + } else { + kdDebug()<<"Checkdirs failed"<<endl; + } + return; + } + QListViewItem*temp; + while ((temp=firstChild())) { + delete temp; + } + m_Dirsread.clear(); + checkDirs(baseUri(),0); + return; + } + svn::StatusPtr stat; + try { + stat = m_SvnWrapper->svnclient()->singleStatus(newdir); + } catch (const svn::ClientException&e) { + m_LastException = e.msg(); + kdDebug()<<"Catched on singlestatus"<< endl; + emit sigLogMessage(m_LastException); + return; + } + FileListViewItem * item,*pitem; + pitem = k; + if (!pitem) { + pitem = (FileListViewItem*)firstChild(); + if (pitem->fullName()!=baseUri()) { + pitem = 0; + } + } + if (!pitem) { + item = new FileListViewItem(this,stat); + } else { + item = new FileListViewItem(this,pitem,stat); + } + if (item->isDir()) { + m_Dirsread[item->fullName()]=false; + item->setDropEnabled(true); + if (isWorkingCopy()) { + m_pList->m_DirWatch->addDir(item->fullName()); + } + } else if (isWorkingCopy()) { + m_pList->m_DirWatch->addFile(item->fullName()); + } +} + +kdesvnfilelist::~kdesvnfilelist() +{ + delete m_pList; + delete m_SelectedItems; + SshAgent ssh; + ssh.killSshAgent(); +} + +void kdesvnfilelist::slotItemRead(QListViewItem*aItem) +{ + if (!aItem) return; + CursorStack a(Qt::BusyCursor); + FileListViewItem* k = static_cast<FileListViewItem*>( aItem ); + bool _ex = true; + if (isWorkingCopy()) { + QDir d(k->fullName()); //FIXME: remove this as soon as we've been able to set entry->kind in Checkdirs + _ex = k->isDir()||d.exists(); + } else { + _ex = k->isDir(); + } + + if (_ex &&(m_Dirsread.find(k->fullName())==m_Dirsread.end()||m_Dirsread[k->fullName()]==false)) { + if (checkDirs(k->fullName(),k)) { + m_Dirsread[k->fullName()]=true; + } else { + emit sigListError(); + } + } +} + +void kdesvnfilelist::slotReinitItem(SvnItem*item) +{ + if (!item) { + kdDebug()<<"kdesvnfilelist::slotReinitItem(SvnItem*item): item == null" << endl; + return; + } + FileListViewItem*k = item->fItem(); + if (!k) { + kdDebug()<<"kdesvnfilelist::slotReinitItem(SvnItem*item): k == null" << endl; + } + refreshItem(k); + if (!k) { + return; + } + if (k->isDir()) { + k->removeChilds(); + m_Dirsread[k->fullName()]=false;; + } +} + +void kdesvnfilelist::enableActions() +{ + bool isopen = baseUri().length()>0; + int c = allSelected()->count(); + bool single = c==1&&isopen; + bool multi = c>1&&isopen; + bool none = c==0&&isopen; + bool dir = false; + bool unique = uniqueTypeSelected(); + bool remote_enabled=isopen&&m_SvnWrapper->doNetworking(); + + if (single && allSelected()->at(0)->isDir()) { + dir = true; + } + + bool conflicted = single && allSelected()->at(0)->isConflicted(); + KAction * temp = 0; + /* local and remote actions */ + /* 1. actions on dirs AND files */ + temp = filesActions()->action("make_svn_log"); + if (temp) { + temp->setEnabled(single||none); + } + temp = filesActions()->action("make_last_change"); + if (temp) { + temp->setEnabled(isopen); + } + + temp = filesActions()->action("make_svn_log_full"); + if (temp) { + temp->setEnabled(single||none); + } + temp = filesActions()->action("make_svn_tree"); + if (temp) { + temp->setEnabled(single||none); + } + temp = filesActions()->action("make_svn_partialtree"); + if (temp) { + temp->setEnabled(single||none); + } + + temp = filesActions()->action("make_svn_property"); + if (temp) { + temp->setEnabled(single); + } + temp = filesActions()->action("get_svn_property"); + if (temp) { + temp->setEnabled(single); + } + m_DelCurrent->setEnabled( (multi||single)); + m_LockAction->setEnabled( (multi||single)); + m_UnlockAction->setEnabled( (multi||single)); + m_IgnoreAction->setEnabled((single)&&singleSelected()->parent()!=0&&!singleSelected()->isRealVersioned()); + + m_RenameAction->setEnabled(single && (!isWorkingCopy()||singleSelected()!=firstChild())); + m_CopyAction->setEnabled(single && (!isWorkingCopy()||singleSelected()!=firstChild())); + + /* 2. only on files */ + m_BlameAction->setEnabled(single&&!dir&&remote_enabled); + m_BlameRangeAction->setEnabled(single&&!dir&&remote_enabled); + m_CatAction->setEnabled(single&&!dir); + /* 3. actions only on dirs */ + m_MkdirAction->setEnabled(dir||none && isopen); + m_switchRepository->setEnabled(isWorkingCopy()&& (single||none)); + m_changeToRepository->setEnabled(isWorkingCopy()); + m_ImportDirsIntoCurrent->setEnabled(dir); + temp = filesActions()->action("make_svn_relocate"); + if (temp) { + temp->setEnabled(isWorkingCopy()&& (single||none)); + } + m_ExportCurrentAction->setEnabled(((single&&dir)||none)); + + /* local only actions */ + /* 1. actions on files AND dirs*/ + m_AddCurrent->setEnabled( (multi||single) && isWorkingCopy()); + m_RevertAction->setEnabled( (multi||single) && isWorkingCopy()); + m_ResolvedAction->setEnabled( (multi||single) && isWorkingCopy()); + temp = filesActions()->action("make_try_resolve"); + if (temp) { + temp->setEnabled(conflicted && !dir); + } + + m_InfoAction->setEnabled(isopen); + m_MergeRevisionAction->setEnabled(single&&isWorkingCopy()); + temp = filesActions()->action("make_svn_merge"); + if (temp) { + temp->setEnabled(single||none); + } + temp = filesActions()->action("make_svn_addrec"); + if (temp) { + temp->setEnabled( (multi||single) && isWorkingCopy()); + } + m_UpdateHead->setEnabled(isWorkingCopy()&&isopen&&remote_enabled); + m_UpdateRev->setEnabled(isWorkingCopy()&&isopen&&remote_enabled); + m_commitAction->setEnabled(isWorkingCopy()&&isopen&&remote_enabled); + + temp = filesActions()->action("make_svn_basediff"); + if (temp) { + temp->setEnabled(isWorkingCopy()&&(single||none)); + } + temp = filesActions()->action("make_svn_headdiff"); + if (temp) { + temp->setEnabled(isWorkingCopy()&&(single||none)&&remote_enabled); + } + + /// @todo check if all items have same type + temp = filesActions()->action("make_svn_itemsdiff"); + if (temp) { + temp->setEnabled(multi && c==2 && unique && remote_enabled); + } + + /* 2. on dirs only */ + m_CleanupAction->setEnabled(isWorkingCopy()&& (dir||none)); + temp = filesActions()->action("make_check_unversioned"); + if (temp) { + temp->setEnabled(isWorkingCopy()&& ((dir&&single) || none)); + } + + /* remote actions only */ + m_CheckoutCurrentAction->setEnabled( ((single&&dir)||none) && !isWorkingCopy() && remote_enabled); + /* independ actions */ + m_CheckoutAction->setEnabled(remote_enabled); + m_ExportAction->setEnabled(true); + m_RefreshViewAction->setEnabled(isopen); + + temp = filesActions()->action("make_revisions_diff"); + if (temp) { + temp->setEnabled(isopen); + } + temp = filesActions()->action("make_revisions_cat"); + if (temp) { + temp->setEnabled(isopen && !dir && single); + } + temp = filesActions()->action("switch_browse_revision"); + if (temp) { + temp->setEnabled(!isWorkingCopy()&&isopen); + } + temp = filesActions()->action("make_check_updates"); + if (temp) { + temp->setEnabled(isWorkingCopy()&&isopen && remote_enabled); + } + temp = filesActions()->action("openwith"); + if (temp) { + temp->setEnabled(kapp->authorizeKAction("openwith")&&single&&!dir); + } + + temp = filesActions()->action("update_log_cache"); + if (temp) { + temp->setEnabled(remote_enabled); + if (!m_SvnWrapper->threadRunning(SvnActions::fillcachethread)) { + temp->setText(i18n("Update log cache")); + } else { + temp->setText(i18n("Stop updating the logcache")); + } + } +} + +void kdesvnfilelist::slotSelectionChanged() +{ + m_pList->stopProptimer(); + if (m_SelectedItems==0) { + m_SelectedItems = new FileListViewItemList; + m_SelectedItems->setAutoDelete(false); + } + m_SelectedItems->clear(); + + QListViewItemIterator it( this, QListViewItemIterator::Selected ); + while ( it.current() ) { + m_SelectedItems->append( static_cast<FileListViewItem*>(it.current()) ); + ++it; + } + enableActions(); + m_pList->startProptimer(); +} + +/*! + \fn kdesvnfilelist::slotClientException(const QString&) + */ +void kdesvnfilelist::slotClientException(const QString&what) +{ + emit sigLogMessage(what); + KMessageBox::sorry(KApplication::activeModalWidget(),what,i18n("SVN Error")); +} + + +/*! + \fn kdesvnfilelist::slotNotifyMessage(const QString&) + */ +void kdesvnfilelist::slotNotifyMessage(const QString&what) +{ + emit sigLogMessage(what); + kapp->processEvents(20); +} + +void kdesvnfilelist::slotChangeToRepository() +{ + if (!isWorkingCopy()) { + return; + } + FileListViewItem*k = static_cast<FileListViewItem*>(firstChild()); + /* huh... */ + if (!k) return; + svn::InfoEntry i; + if (!m_SvnWrapper->singleInfo(k->Url(),svn::Revision::UNDEFINED,i)) { + return; + } + if (i.reposRoot().isEmpty()) { + KMessageBox::sorry(KApplication::activeModalWidget(),i18n("Could not retrieve repository of working copy."),i18n("SVN Error")); + } else { + sigSwitchUrl(i.reposRoot()); + } +} + +void kdesvnfilelist::slotItemDoubleClicked(QListViewItem*item) +{ + if (!item) return; + + FileListViewItem*fki = static_cast<FileListViewItem*>(item); + if (fki->isDir()) { + if (fki->isOpen()) { + fki->setOpen(false); + } else { + fki->setOpen(true); + } + return; + } + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + QString feditor = Kdesvnsettings::external_display(); + if ( feditor.compare("default") == 0 ) { + KURL::List lst; + lst.append(fki->kdeName(rev)); + KTrader::OfferList li = offersList(fki,true); + if (li.count()==0||li.first()->exec().isEmpty()) { + li = offersList(fki); + } + if (li.count()>0&&!li.first()->exec().isEmpty()) { + KService::Ptr ptr = li.first(); + KRun::run( *ptr, lst); + } else { + KRun::displayOpenWithDialog(lst); + } + } else { + if ( KRun::runCommand(feditor + " " + fki->kdeName(rev).prettyURL()) <= 0) { + KMessageBox::error(this,i18n("Failed: %1 %2").arg(feditor).arg(fki->fullName())); + } + } +} + +void kdesvnfilelist::slotCleanupAction() +{ + if (!isWorkingCopy()) return; + FileListViewItem*which= singleSelected(); + if (!which) which = static_cast<FileListViewItem*>(firstChild()); + if (!which||!which->isDir()) return; + if (m_SvnWrapper->makeCleanup(which->fullName())) { + which->refreshStatus(true); + } +} + +void kdesvnfilelist::slotResolved() +{ + if (!isWorkingCopy()) return; + FileListViewItem*which= singleSelected(); + if (!which) which = static_cast<FileListViewItem*>(firstChild()); + if (!which) return; + m_SvnWrapper->slotResolved(which->fullName()); + which->refreshStatus(true); + slotRescanIcons(false); +} + +void kdesvnfilelist::slotTryResolve() +{ + if (!isWorkingCopy()) return; + FileListViewItem*which= singleSelected(); + if (!which || which->isDir()) { + return; + } + m_SvnWrapper->slotResolve(which->fullName()); +} + +template<class T> KDialogBase* kdesvnfilelist::createDialog(T**ptr,const QString&_head,bool OkCancel,const char*name,bool showHelp) +{ + int buttons = KDialogBase::Ok; + if (OkCancel) { + buttons = buttons|KDialogBase::Cancel; + } + if (showHelp) { + buttons = buttons|KDialogBase::Help; + } + KDialogBase * dlg = new KDialogBase( + KApplication::activeModalWidget(), + name, + true, + _head, + buttons); + + if (!dlg) return dlg; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + *ptr = new T(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),name?name:"standard_size")); + return dlg; +} + +void kdesvnfilelist::slotImportDirsIntoCurrent() +{ + slotImportIntoCurrent(true); +} + +/*! + \fn kdesvnfilelist::slotImportIntoCurrent() + */ +void kdesvnfilelist::slotImportIntoCurrent(bool dirs) +{ + if (allSelected()->count()>1) { + KMessageBox::error(this,i18n("Cannot import into multiple targets!")); + return; + } + QString targetUri; + if (allSelected()->count()==0) { + targetUri=baseUri(); + } else { + targetUri = allSelected()->at(0)->Url(); + } + KURL uri; + if (dirs) uri = KFileDialog::getExistingDirectory(QString::null,this,"Import files from folder"); + else uri = KFileDialog::getImageOpenURL(QString::null,this,"Import file"); + + if (uri.url().isEmpty()) return; + + if ( !uri.protocol().isEmpty() && uri.protocol()!="file") { + KMessageBox::error(this,i18n("Cannot import into remote targets!")); + return; + } + slotImportIntoDir(uri,targetUri,dirs); +} + +void kdesvnfilelist::slotImportIntoDir(const KURL&importUrl,const QString&target,bool dirs) +{ + Logmsg_impl*ptr; + Importdir_logmsg*ptr2 = 0; + + KDialogBase*dlg; + KURL uri = importUrl; + QString targetUri = target; + while (targetUri.endsWith("/")) { + targetUri.truncate(targetUri.length()-1); + } + + if (dirs) { + dlg = createDialog(&ptr2,QString(i18n("Import log")),true,"import_log_msg"); + ptr = ptr2; + ptr2->createDirboxDir("\""+uri.fileName(true)+"\""); + } else { + dlg = createDialog(&ptr,QString(i18n("Import log")),true,"import_log_msg"); + } + + if (!dlg) return; + + ptr->initHistory(); + if (dlg->exec()!=QDialog::Accepted) { + ptr->saveHistory(true); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"import_log_msg",false); + delete dlg; + return; + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"import_log_msg",false); + + QString logMessage = ptr->getMessage(); + svn::Depth rec = ptr->getDepth(); + ptr->saveHistory(false); + uri.setProtocol(""); + QString iurl = uri.path(); + while (iurl.endsWith("/")) { + iurl.truncate(iurl.length()-1); + } + + if (dirs && ptr2 && ptr2->createDir()) { + targetUri+= "/"+uri.fileName(true); + } + if (ptr2) { + m_SvnWrapper->slotImport(iurl,targetUri,logMessage,rec,ptr2->noIgnore(),ptr2->ignoreUnknownNodes()); + } else { + m_SvnWrapper->slotImport(iurl,targetUri,logMessage,rec,false,false); + } + + if (!isWorkingCopy()) { + if (allSelected()->count()==0) { + refreshCurrentTree(); + } else { + refreshCurrent(allSelected()->at(0)); + } + } + delete dlg; +} + +void kdesvnfilelist::readSupportData() +{ + /// this moment empty cause no usagedata explicit used by kdesvnfilelist +} + +void kdesvnfilelist::refreshCurrentTree() +{ + QTime t; + t.start(); + FileListViewItem*item = static_cast<FileListViewItem*>(firstChild()); + if (!item) return; + //m_pList->stopScan(); + m_pList->m_fileTip->setItem(0); + kapp->processEvents(); + setUpdatesEnabled(false); + if (item->fullName()==baseUri()) { + if (!refreshItem(item)) { + setUpdatesEnabled(true); + viewport()->repaint(); + return; + } else { + refreshRecursive(item); + } + } else { + refreshRecursive(0); + } + if (isWorkingCopy()) { + m_SvnWrapper->createModifiedCache(baseUri()); + } + kdDebug()<<"Refresh time: "<<t.elapsed()<<" ms"<<endl; + setUpdatesEnabled(true); + viewport()->repaint(); + QTimer::singleShot(1,this,SLOT(readSupportData())); + //m_pList->startScan(); +} + +void kdesvnfilelist::refreshCurrent(SvnItem*cur) +{ + if (!cur||!cur->fItem()) { + refreshCurrentTree(); + return; + } + kapp->processEvents(); + setUpdatesEnabled(false); + refreshRecursive(cur->fItem()); + setUpdatesEnabled(true); + viewport()->repaint(); +} + +bool kdesvnfilelist::refreshRecursive(FileListViewItem*_parent,bool down) +{ + FileListViewItem*item; + if (_parent) { + item = static_cast<FileListViewItem*>(_parent->firstChild()); + } else { + item = static_cast<FileListViewItem*>(firstChild()); + } + + if (!item) return false; + kapp->processEvents(); + + FileListViewItemList currentSync; + currentSync.setAutoDelete(false); + + while (item) { + currentSync.append(item); + item = static_cast<FileListViewItem*>(item->nextSibling()); + } + + QString what = (_parent!=0?_parent->fullName():baseUri()); + svn::StatusEntries dlist; + + if (!m_SvnWrapper->makeStatus(what,dlist,m_pList->m_remoteRevision)) { + kdDebug()<<"Fehler bei makestatus fuer "<<what <<endl; + return false; + } + if (isWorkingCopy()) { + svn::StatusEntries neweritems; + m_SvnWrapper->getaddedItems(what,neweritems); + dlist+=neweritems; + } + + svn::StatusEntries::iterator it = dlist.begin(); + FileListViewItem*k; + bool gotit = false; + bool dispchanged = false; + for (;it!=dlist.end();++it) { + gotit = false; + if ((*it)->path()==what) { + continue; + } + FileListViewItemListIterator clistIter(currentSync); + while ( (k=clistIter.current()) ) { + ++clistIter; + if (k->fullName()==(*it)->path()) { + currentSync.removeRef(k); + k->updateStatus(*it); + if (filterOut(k)) { + dispchanged=true; + delete k; + } + gotit = true; + break; + } + } + if (!gotit &&!filterOut((*it)) ) { + dispchanged = true; + FileListViewItem * item; + if (!_parent) { + item = new FileListViewItem(this,*it); + } else { + item = new FileListViewItem(this,_parent,*it); + } + if (item->isDir()) { + m_Dirsread[item->fullName()]=false; + item->setDropEnabled(true); + } + if (isWorkingCopy()) { + if (item->isDir()) { + m_pList->m_DirWatch->addDir(item->fullName()); + } else { + m_pList->m_DirWatch->addFile(item->fullName()); + } + } + } + } + FileListViewItemListIterator dIter(currentSync); +#ifndef NDEBUG + slotSelectionChanged(); + kdDebug() << "Selected items " << m_SelectedItems->count()<< endl; +#endif + while ( (k=dIter.current()) ) { + ++dIter; + delete k; + // @todo just for debugging! +#ifndef NDEBUG + m_SelectedItems->clear(); + QListViewItemIterator qlvit( this, QListViewItemIterator::Selected ); + while ( qlvit.current() ) { + m_SelectedItems->append( static_cast<FileListViewItem*>(qlvit.current()) ); + ++qlvit; + } + kdDebug() << "Selected items " << m_SelectedItems->count() << endl; +#endif + } + if (_parent) { + item = static_cast<FileListViewItem*>(_parent->firstChild()); + } else { + item = static_cast<FileListViewItem*>(firstChild()); + } + if (!down) { + return dispchanged; + } + while (item) { + if (item->isDir()) { + if ((m_Dirsread.find(item->fullName())!=m_Dirsread.end()&&m_Dirsread[item->fullName()]==true)) { + if (item->childCount()==0) { + checkDirs(item->fullName(),item); + dispchanged = true; + } else { + dispchanged = refreshRecursive(item)?true:dispchanged; + } + } + } + item = static_cast<FileListViewItem*>(item->nextSibling()); + } + return dispchanged; +} + +KTrader::OfferList kdesvnfilelist::offersList(SvnItem*item,bool execOnly) +{ + KTrader::OfferList offers; + if (!item) { + return offers; + } + QString constraint; + if (execOnly) { + constraint = "Type == 'Application' or (exist Exec)"; + } else { + constraint = "Type == 'Application'"; + } + offers = KTrader::self()->query(item->mimeType()->name(), constraint); + + return offers; +} + +void kdesvnfilelist::slotContextMenuRequested(QListViewItem */* _item */, const QPoint &, int) +{ +// FileListViewItem*item = static_cast<FileListViewItem*>(_item); + bool isopen = baseUri().length()>0; + SvnItemList l; + SelectionList(&l); + + QString menuname; + + if (!isopen) { + menuname="empty"; + } else if (isWorkingCopy()) { + menuname="local"; + } else { + menuname="remote"; + } + if (l.count()==0) { + menuname+="_general"; + } else if (l.count()>1){ + menuname+="_context_multi"; + } else { + menuname+="_context_single"; + if (isWorkingCopy()) { + if (l.at(0)->isRealVersioned()) { + if (l.at(0)->isConflicted()) { + menuname+="_conflicted"; + } else { + menuname+="_versioned"; + if (l.at(0)->isDir()) { + menuname+="_dir"; + } + } + } else { + menuname+="_unversioned"; + } + } else if (l.at(0)->isDir()) { + menuname+="_dir"; + } + } + + QWidget * target; + emit sigShowPopup(menuname,&target); + QPopupMenu *popup = static_cast<QPopupMenu *>(target); + if (!popup) { + kdDebug()<<"Error getting popupMenu"<<endl; + return; + } + + KTrader::OfferList offers; + OpenContextmenu*me=0; + KAction*temp = 0; + + int id = -1; + + if (l.count()==1) offers = offersList(l.at(0)); + + if (l.count()==1&&!l.at(0)->isDir()) { + temp = filesActions()->action("openwith"); + if (offers.count()>0) { + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + me= new OpenContextmenu(l.at(0)->kdeName(rev),offers,0,0); + id = popup->insertItem(i18n("Open With..."),me); + } else { + temp = filesActions()->action("openwith"); + if (temp) { + temp->plug(popup); + } + } + } + popup->exec(QCursor::pos()); + if (id>-1) { + popup->removeItem(id); + } + delete me; + if (temp) { + temp->unplug(popup); + } +} + +/** +* Overridden virtuals for Qt drag 'n drop (XDND) +*/ +void kdesvnfilelist::contentsDragEnterEvent(QDragEnterEvent *event) +{ + QListViewItem*item; + bool ok = validDropEvent(event,item); + if (ok) { + event->accept(); + } else { + event->ignore(); + } +} + +//void kdesvnfilelist::startDrag() +QDragObject* kdesvnfilelist::dragObject() +{ + m_pList->m_fileTip->setItem(0); + QListViewItem * m_pressedItem = currentItem(); + if (!m_pressedItem) { + return 0; + } + QPixmap pixmap2; + KURL::List urls = selectedUrls(); + if (urls.count()==0) { + return 0; + } + if (!viewport()->hasFocus()) { + kdDebug()<<"Set focus"<<endl; + viewport()->setFocus(); + } + kdDebug() << "dragObject: " << urls << endl; + bool pixmap0Invalid = !m_pressedItem->pixmap(0) || m_pressedItem->pixmap(0)->isNull(); + if (( urls.count() > 1 ) || (pixmap0Invalid)) { + int iconSize = Kdesvnsettings::listview_icon_size();; + iconSize = iconSize ? iconSize : kdesvnPartFactory::instance()->iconLoader()->currentSize( KIcon::Small ); // Default = small + pixmap2 = DesktopIcon( "kmultiple", iconSize ); + if ( pixmap2.isNull() ) { + kdWarning() << "Could not find multiple pixmap" << endl; + } + } + + KURLDrag *drag; + drag = new KURLDrag(urls,viewport()); + + /* workaround for KURL::Drag - it always forget the revision part on drop :( */ + if (!isWorkingCopy()) { + QStrList l; + QString t; + KURL::List::ConstIterator it = urls.begin(); + for (;it!=urls.end();++it) { + l.append((*it).prettyURL()); + } + drag->setUris(l); + } + + drag->setExportAsText(true); + if ( !pixmap2.isNull() ) + drag->setPixmap( pixmap2 ); + else if ( !pixmap0Invalid ) + drag->setPixmap( *m_pressedItem->pixmap( 0 ) ); + + return drag; +} + +void kdesvnfilelist::contentsDragLeaveEvent( QDragLeaveEvent * ) +{ + cleanHighLighter(); +} + +bool kdesvnfilelist::acceptDrag(QDropEvent *event)const +{ + return KURLDrag::canDecode(event); +} + +bool kdesvnfilelist::validDropEvent(QDropEvent*event,QListViewItem*&item) +{ + if (!event) return false; + if (!isWorkingCopy()) { + if (m_pList->m_remoteRevision!=svn::Revision::HEAD) { + item = 0; + return false; + } + } + bool ok = false; + item = 0; + if (KURLDrag::canDecode(event)) { + KURL::List urlList; + KURLDrag::decode( event, urlList ); + int count = urlList.count(); + if (count>0) { + if (baseUri().length()==0) { + ok = true; + } else { + QPoint vp = contentsToViewport( event->pos() ); + item = isExecuteArea( vp ) ? itemAt( vp ) : 0L; + FileListViewItem*which=static_cast<FileListViewItem*>(item); + if (!isWorkingCopy()) { + if (event->source()!=viewport()){ + ok = (!item || (which->isDir()))&&urlList[0].isLocalFile()&&count==1; + } else { + ok = (!item || (which->isDir() )); + } + } else { + ok = (which && (which->isDir())); + } + } + } + } + return ok; +} + +void kdesvnfilelist::contentsDropEvent(QDropEvent * event) +{ + QListViewItem *item = 0; + bool ok = validDropEvent(event,item); + cleanHighLighter(); + if (ok) { + dropped(event,item); + } else { + event->ignore(); + } +} + +void kdesvnfilelist::contentsDragMoveEvent( QDragMoveEvent* event) +{ + QListViewItem * item; + bool ok = validDropEvent(event,item); + + if (item && item!=m_pList->dragOverItem) { + QPoint vp = contentsToViewport( event->pos() ); + m_pList->dragOverItem=item; + m_pList->dragOverPoint = vp; + QRect tmpRect = drawItemHighlighter(0, m_pList->dragOverItem); + if (tmpRect!=m_pList->mOldDropHighlighter) { + cleanHighLighter(); + m_pList->mOldDropHighlighter=tmpRect; + viewport()->repaint(tmpRect); + kapp->processEvents(); + } + } + if (ok) { + event->accept(); + } else { + event->ignore(); + } +} + +void kdesvnfilelist::viewportPaintEvent(QPaintEvent *ev) +{ + KListView::viewportPaintEvent(ev); + if (m_pList->mOldDropHighlighter.isValid() && ev->rect().intersects(m_pList->mOldDropHighlighter)) { + QPainter painter(viewport()); + style().drawPrimitive(QStyle::PE_FocusRect, &painter, m_pList->mOldDropHighlighter, colorGroup(), + QStyle::Style_FocusAtBorder); + } +} + +void kdesvnfilelist::cleanHighLighter() +{ + if (m_pList->mOldDropHighlighter.isValid()) { + QRect rect=m_pList->mOldDropHighlighter; + m_pList->mOldDropHighlighter=QRect(); + viewport()->repaint(rect, true); + } +} + +/*! + \fn kdesvnfilelist::slotMergeRevisions() + */ +void kdesvnfilelist::slotMergeRevisions() +{ + if (!isWorkingCopy()) return; + FileListViewItem*which= singleSelected(); + if (!which) { + return; + } + bool force,dry,rec,irelated,useExternal; + Rangeinput_impl::revision_range range; + if (!MergeDlg_impl::getMergeRange(range,&force,&rec,&irelated,&dry,&useExternal,this,"merge_range")) { + return; + } + if (!useExternal) { + m_SvnWrapper->slotMergeWcRevisions(which->fullName(),range.first,range.second,rec,!irelated,force,dry); + } else { + m_SvnWrapper->slotMergeExternal(which->fullName(),which->fullName(),which->fullName(),range.first,range.second, + isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision,rec); + } + refreshItem(which); + refreshRecursive(which); +} + +void kdesvnfilelist::slotMerge() +{ + FileListViewItem*which= singleSelected(); + QString src1,src2,target; + if (isWorkingCopy()) { + if (m_pList->merge_Target.isEmpty()) { + target = which?which->fullName():baseUri(); + } else { + target = m_pList->merge_Target; + } + src1 = m_pList->merge_Src1; + } else { + if (m_pList->merge_Src1.isEmpty()){ + src1 = which?which->fullName():baseUri(); + } else { + src1 = m_pList->merge_Src1; + } + target = m_pList->merge_Target; + } + src2 = m_pList->merge_Src2; + bool force,dry,rec,irelated,useExternal; + Rangeinput_impl::revision_range range; + MergeDlg_impl*ptr; + KDialogBase*dlg = createDialog(&ptr,QString(i18n("Merge")),true,"merge_dialog",true); + if (!dlg) { + return; + } + dlg->setHelp("merging-items","kdesvn"); + ptr->setDest(target); + ptr->setSrc1(src1); + ptr->setSrc2(src1); + if (dlg->exec()==QDialog::Accepted) { + src1=ptr->Src1(); + src2=ptr->Src2(); + if (src2.isEmpty()) { + src2 = src1; + } + target = ptr->Dest(); + m_pList->merge_Src2 = src2; + m_pList->merge_Src1 = src1; + m_pList->merge_Target = target; + force = ptr->force(); + dry = ptr->dryrun(); + rec = ptr->recursive(); + irelated = ptr->ignorerelated(); + useExternal = ptr->useExtern(); + range = ptr->getRange(); + if (!useExternal) { + m_SvnWrapper->slotMerge(src1,src2,target,range.first,range.second, + isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision, + rec,!irelated,force,dry); + } else { + m_SvnWrapper->slotMergeExternal(src1,src2,target,range.first,range.second, + isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision,rec); + } + if (isWorkingCopy()) { +// refreshItem(which); +// refreshRecursive(which); + refreshCurrentTree(); + } + } + + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"merge_dialog",false); + + delete dlg; +} + +void kdesvnfilelist::slotDropped(QDropEvent* event,QListViewItem*item) +{ + KURL::List urlList; + QMap<QString,QString> metaData; + QDropEvent::Action action = event->action(); + if (!event || m_pList->intern_dropRunning||!KURLDrag::decode( event, urlList, metaData)||urlList.count()<1) { + return; + } + kdDebug()<<"slotDropped"<<endl; + QString tdir; + if (item) { + FileListViewItem*which = static_cast<FileListViewItem*>(item); + clearSelection(); + which->setSelected(true); + kapp->processEvents(); + tdir = which->fullName(); + } else { + tdir = baseUri(); + } + + if (event->source()!=viewport()) { + kdDebug()<<"Dropped from outside" << endl; + if (baseUri().length()==0) { + openURL(urlList[0]); + event->acceptAction(); + return; + } + if (baseUri().length()>0 /*&& urlList[0].isLocalFile()*/) { + QString path = urlList[0].path(); + QFileInfo fi(path); + if (!isWorkingCopy()) { + slotImportIntoDir(urlList[0],tdir,fi.isDir()); + } else { + //m_pList->stopScan(); + KIO::Job * job = 0L; + job = KIO::copy(urlList,tdir); + connect( job, SIGNAL( result( KIO::Job * ) ),SLOT( slotCopyFinished( KIO::Job * ) ) ); + dispDummy(); + event->acceptAction(); + return; + } + } + } else { + kdDebug()<<"Dropped from inside " << action << endl; + int root_x, root_y, win_x, win_y; + uint keybstate; + QDropEvent::Action action = QDropEvent::UserAction; + KeyState::keystate(&root_x,&root_y,&win_x,&win_y,&keybstate); + if (keybstate&Qt::ControlButton) { + kdDebug()<<"Control pressed" << endl; + action = QDropEvent::Copy; + } else if (keybstate&Qt::ShiftButton) { + kdDebug()<<"Shift pressed" << endl; + action = QDropEvent::Move; + } + /* converting urls to interal style */ + QString nProto; + if (isWorkingCopy()) { + nProto=""; + } else { + nProto = svn::Url::transformProtokoll(urlList[0].protocol()); + } + KURL::List::Iterator it = urlList.begin(); + QStringList l; + for (;it!=urlList.end();++it) { + l = QStringList::split("?",(*it).prettyURL()); + if (l.size()>1) { + (*it) = l[0]; + } else if (isWorkingCopy()) + { + (*it) = KURL::fromPathOrURL( (*it).path()); + } + (*it).setProtocol(nProto); + kdDebug()<<"Dropped: "<<(*it)<<endl; + } + event->acceptAction(); + m_pList->intern_dropRunning=true; + m_pList->intern_drops = urlList; + m_pList->intern_drop_target=tdir; + m_pList->intern_drop_action=action; + m_pList->intern_drop_pos=QCursor::pos(); + QTimer::singleShot(0,this,SLOT(slotInternalDrop())); + +// internalDrop(action,urlList,tdir); + } +} + +void kdesvnfilelist::slotInternalDrop() +{ + QDropEvent::Action action = m_pList->intern_drop_action; + if (action==QDropEvent::UserAction) { + QPopupMenu popup; + popup.insertItem(SmallIconSet("goto"), i18n( "Move Here" ) + "\t" + KKey::modFlagLabel( KKey::SHIFT ), 2 ); + popup.insertItem(SmallIconSet("editcopy"), i18n( "Copy Here" ) + "\t" + KKey::modFlagLabel( KKey::CTRL ), 1 ); + popup.insertSeparator(); + popup.insertItem(SmallIconSet("cancel"), i18n( "Cancel" ) + "\t" + KKey( Qt::Key_Escape ).toString(), 5); + int result = popup.exec(m_pList->intern_drop_pos); + switch (result) { + case 1 : action = QDropEvent::Copy; break; + case 2 : action = QDropEvent::Move; break; + default: + { + m_pList->intern_dropRunning=false; + return; + } + } + } + if (action==QDropEvent::Move) { + m_SvnWrapper->makeMove(m_pList->intern_drops,m_pList->intern_drop_target,false); + } else { + m_SvnWrapper->makeCopy(m_pList->intern_drops,m_pList->intern_drop_target,svn::Revision::HEAD); + } + m_pList->intern_dropRunning=false; + refreshCurrentTree(); +} + +/*! + \fn kdesvnfilelist::slotRename() + */ +void kdesvnfilelist::slotRename() +{ + copy_move(true); +} +void kdesvnfilelist::slotCopy() +{ + copy_move(false); +} + +void kdesvnfilelist::copy_move(bool move) +{ + if (isWorkingCopy()&&singleSelected()==firstChild()) { + return; + } + bool ok, force; + FileListViewItem*which = singleSelected(); + if (!which) return; + QString nName = CopyMoveView_impl::getMoveCopyTo(&ok,&force,move, + which->fullName(),baseUri(),this,"move_name"); + if (!ok) { + return; + } + if (move) { + m_SvnWrapper->makeMove(which->fullName(),nName,force); + } else { + m_SvnWrapper->makeCopy(which->fullName(),nName, isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision); + } +} + +void kdesvnfilelist::slotCat() +{ + FileListViewItem*k = singleSelected(); + if (!k) return; + m_SvnWrapper->slotMakeCat(isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision, k->fullName(),k->text(0), + isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision,0); +} + + +/*! + \fn kdesvnfilelist::slotCopyFinished( KIO::Job *) + */ +void kdesvnfilelist::slotCopyFinished( KIO::Job * job) +{ + if (m_pList->m_DirWatch) { + m_pList->m_DirWatch->startScan(false); + } + if (job) { + bool ok = true; + qApp->exit_loop(); + if (job->error()) { + job->showErrorDialog(this); + ok = false; + } + // always just connect a CopyJob here!!!! + if (ok) { + KURL::List lst = static_cast<KIO::CopyJob*>(job)->srcURLs(); + KURL turl = static_cast<KIO::CopyJob*>(job)->destURL(); + QString base = turl.path(1); + KURL::List::iterator iter; + QValueList<svn::Path> tmp; + for (iter=lst.begin();iter!=lst.end();++iter) { + tmp.push_back(svn::Path((base+(*iter).fileName(true)))); + } + m_SvnWrapper->addItems(tmp,svn::DepthInfinity); + } + refreshCurrentTree(); + } +} + + + +/*! + \fn kdesvnfilelist::slotDelete() + */ +void kdesvnfilelist::slotDelete() +{ + m_deletePerfect = true; + QPtrList<FileListViewItem>*lst = allSelected(); + + if (lst->count()==0) { + KMessageBox::error(this,i18n("Nothing selected for delete")); + return; + } + FileListViewItemListIterator liter(*lst); + FileListViewItem*cur; + //m_pList->stopScan(); + m_pList->m_fileTip->setItem(0); + + QValueList<svn::Path> items; + QStringList displist; + KURL::List kioList; + while ((cur=liter.current())!=0){ + ++liter; + if (!cur->isRealVersioned()) { + KURL _uri; _uri.setPath(cur->fullName()); + kioList.append(_uri); + } else { + items.push_back(cur->fullName()); + } + displist.append(cur->fullName()); + } + int answer = KMessageBox::questionYesNoList(this,i18n("Really delete these entries?"),displist,i18n("Delete from repository")); + if (answer!=KMessageBox::Yes) { + return; + } + if (kioList.count()>0) { + KIO::Job*aJob = KIO::del(kioList); + connect(aJob,SIGNAL(result (KIO::Job *)),this,SLOT(slotDeleteFinished(KIO::Job*))); + dispDummy(); + } + if (m_deletePerfect && items.size()>0) { + m_SvnWrapper->makeDelete(items); + } + refreshCurrentTree(); + //m_pList->startScan(); +} + +/*! + \fn kdesvnfilelist::slotDeleteFinished(KIO::Job*) + */ +void kdesvnfilelist::slotDeleteFinished(KIO::Job*job) +{ + if (job) { + qApp->exit_loop(); + if (job->error()) { + job->showErrorDialog(this); + m_deletePerfect = false; + } + } +} + +/*! + \fn kdesvnfilelist::dispDummy() + */ +void kdesvnfilelist::dispDummy() +{ + // wait for job + QLabel dummy(this,0,WStyle_NoBorder|WShowModal); + QSize csize = size(); + dummy.setText(i18n("Please wait until job is finished")); + dummy.resize(dummy.minimumSizeHint()); + if (dummy.width()<=width()&&dummy.height()<=height()) { + dummy.move(csize.width()/2-dummy.width()/2,csize.height()/2-dummy.height()/2); + } + dummy.show(); + qApp->enter_loop(); + dummy.hide(); +} + + +/*! + \fn kdesvnfilelist::slotLock() + */ +void kdesvnfilelist::slotLock() +{ + QPtrList<FileListViewItem>*lst = allSelected(); + FileListViewItemListIterator liter(*lst); + FileListViewItem*cur; + if (lst->count()==0) { + KMessageBox::error(this,i18n("Nothing selected for lock")); + return; + } + KDialogBase*dlg; + Logmsg_impl*ptr; + dlg = createDialog(&ptr,QString(i18n("Lock message")),true,"locking_log_msg"); + if (!dlg) return; + ptr->initHistory(); + ptr->hideDepth(true); + QCheckBox*_stealLock = new QCheckBox("",ptr,"create_dir_checkbox"); + _stealLock->setText(i18n("Steal lock?")); + ptr->addItemWidget(_stealLock); + ptr->m_keepLocksButton->hide(); + + if (dlg->exec()!=QDialog::Accepted) { + ptr->saveHistory(true); + delete dlg; + return; + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"locking_log_msg",false); + + QString logMessage = ptr->getMessage(); + bool steal = _stealLock->isChecked(); + ptr->saveHistory(false); + + QStringList displist; + while ((cur=liter.current())!=0){ + ++liter; + displist.append(cur->fullName()); + } + m_SvnWrapper->makeLock(displist,logMessage,steal); + refreshCurrentTree(); +} + + +/*! + \fn kdesvnfilelist::slotUnlock() + */ +void kdesvnfilelist::slotUnlock() +{ + QPtrList<FileListViewItem>*lst = allSelected(); + FileListViewItemListIterator liter(*lst); + FileListViewItem*cur; + if (lst->count()==0) { + KMessageBox::error(this,i18n("Nothing selected for unlock")); + return; + } + int res = KMessageBox::questionYesNoCancel(this,i18n("Break lock or ignore missing locks?"),i18n("Unlocking items")); + if (res == KMessageBox::Cancel) { + return; + } + bool breakit = res==KMessageBox::Yes; + + QStringList displist; + while ((cur=liter.current())!=0){ + ++liter; + displist.append(cur->fullName()); + } + m_SvnWrapper->makeUnlock(displist,breakit); + refreshCurrentTree(); +} + + +/*! + \fn kdesvnfilelist::slotIgnore() + */ +void kdesvnfilelist::slotIgnore() +{ + SvnItem*item = singleSelected(); + if (!item || item->isRealVersioned()) return; + if (m_SvnWrapper->makeIgnoreEntry(item,item->isIgnored())) { + refreshCurrentTree(); + } +} + + +/*! + \fn kdesvnfilelist::slotBlame() + */ +void kdesvnfilelist::slotBlame() +{ + SvnItem*k = singleSelected(); + if (!k) return; + svn::Revision start(svn::Revision::START); + svn::Revision end(svn::Revision::HEAD); + m_SvnWrapper->makeBlame(start,end,k); +} + + +/*! + \fn kdesvnfilelist::slotRangeBlame() + */ +void kdesvnfilelist::slotRangeBlame() +{ + SvnItem*k = singleSelected(); + if (!k) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + if (dlg->exec()==QDialog::Accepted) { + Rangeinput_impl::revision_range r = rdlg->getRange(); + m_SvnWrapper->makeBlame(r.first,r.second,k); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + delete dlg; +} + + +void kdesvnfilelist::slotSimpleBaseDiff() +{ + FileListViewItem*kitem = singleSelected(); + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + + QString what; + if (!kitem) { + what=="."; + } else { + what = relativePath(kitem); + } + // only possible on working copies - so we may say this values + m_SvnWrapper->makeDiff(what,svn::Revision::BASE,svn::Revision::WORKING,svn::Revision::UNDEFINED,kitem?kitem->isDir():true); +} + +void kdesvnfilelist::slotSimpleHeadDiff() +{ + FileListViewItem*kitem = singleSelected(); + QString what; + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + + if (!kitem) { + what="."; + }else{ + what = relativePath(kitem); + } + // only possible on working copies - so we may say this values + m_SvnWrapper->makeDiff(what,svn::Revision::WORKING,svn::Revision::HEAD,svn::Revision::UNDEFINED,kitem?kitem->isDir():true); +} + +void kdesvnfilelist::slotDisplayLastDiff() +{ + FileListViewItem*kitem = singleSelected(); + QString what; + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + svn::Revision end = svn::Revision::PREV; + if (!kitem) { + if (isWorkingCopy()) { + QListViewItem*fi = firstChild(); + kitem = static_cast<FileListViewItem*>(fi); + if (!kitem) { + return; + } + what = relativePath(kitem); + } else { + what=baseUri(); + } + }else{ + what = relativePath(kitem); + } + svn::Revision start; + svn::InfoEntry inf; + if (!kitem) { + // it has to have an item when in working copy, so we know we are in repository view. + if (!m_SvnWrapper->singleInfo(what,m_pList->m_remoteRevision,inf)) { + return; + } + start = inf.cmtRev(); + } else { + start = kitem->cmtRev(); + } + if (!isWorkingCopy()) { + if (!m_SvnWrapper->singleInfo(what,start.revnum()-1,inf)) { + return; + } + end = inf.cmtRev(); + } + m_SvnWrapper->makeDiff(what,end,what,start,realWidget()); +} + +void kdesvnfilelist::slotDiffPathes() +{ + QPtrList<FileListViewItem>*lst = allSelected(); + + if (lst->count()!=2 || !uniqueTypeSelected()) { + return; + } + m_pList->m_fileTip->setItem(0); + + FileListViewItem*k1,*k2; + k1 = lst->at(0); + k2 = lst->at(1); + QString w1,w2; + svn::Revision r1; + + if (isWorkingCopy()) { + chdir(baseUri().local8Bit()); + w1 = relativePath(k1); + w2 = relativePath(k2); + r1 = svn::Revision::WORKING; + } else { + w1 = k1->fullName(); + w2 = k2->fullName(); + r1 = m_pList->m_remoteRevision; + } + m_SvnWrapper->makeDiff(w1,r1,w2,r1); +} + +/*! + \fn kdesvnfilelist::slotMkdir() + */ +void kdesvnfilelist::slotMkdir() +{ + SvnItem*k = singleSelected(); + QString parentDir; + if (k) { + if (!k->isDir()) { + KMessageBox::sorry(0,i18n("May not make subdirs of a file")); + return; + } + parentDir=k->fullName(); + } else { + parentDir=baseUri(); + } + QString ex = m_SvnWrapper->makeMkdir(parentDir); + if (!ex.isEmpty()) { + slotDirAdded(ex,static_cast<FileListViewItem*>(k)); + } +} + +void kdesvnfilelist::slotMkBaseDirs() +{ + bool isopen = baseUri().length()>0; + if (!isopen) { + return; + } + QString parentDir=baseUri(); + QStringList targets; + targets.append(parentDir+"/trunk"); + targets.append(parentDir+"/branches"); + targets.append(parentDir+"/tags"); + QString msg = i18n("Automatic generated base layout by kdesvn"); + isopen = m_SvnWrapper->makeMkdir(targets,msg); + if (isopen) { + slotDirAdded(targets[0],0); +// slotDirAdded(targets[1],0); +// slotDirAdded(targets[2],0); + } +} + +/*! + \fn kdesvnfilelist::slotDiffRevisions() + */ +void kdesvnfilelist::slotDiffRevisions() +{ + SvnItem*k = singleSelected(); + QString what; + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + + if (!k) { + what=(isWorkingCopy()?".":baseUri()); + }else{ + what = relativePath(k); + } + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + if (dlg->exec()==QDialog::Accepted) { + Rangeinput_impl::revision_range r = rdlg->getRange(); + svn::Revision _peg=(isWorkingCopy()?svn::Revision::WORKING:remoteRevision()); + m_SvnWrapper->makeDiff(what,r.first,r.second,_peg,k?k->isDir():true); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + delete dlg; + +} + +void kdesvnfilelist::slotSelectBrowsingRevision() +{ + if (isWorkingCopy()) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + rdlg->setStartOnly(true); + if (dlg->exec()==QDialog::Accepted) { + Rangeinput_impl::revision_range r = rdlg->getRange(); + m_pList->m_remoteRevision= r.first; + if (childCount()==0) { + checkDirs(baseUri(),0); + } else { + refreshCurrentTree(); + } + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + delete dlg; +} + +/*! + \fn kdesvnfilelist::slotRevisionCat() + */ +void kdesvnfilelist::slotRevisionCat() +{ + SvnItem*k = singleSelected(); + if (!k) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + rdlg->setStartOnly(true); + if (dlg->exec()==QDialog::Accepted) { + Rangeinput_impl::revision_range r = rdlg->getRange(); + m_SvnWrapper->slotMakeCat(r.first, k->fullName(),k->shortName(),r.first,0); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + delete dlg; +} + + +/*! + \fn kdesvnfilelist::refreshItem(FileListViewItem*) + */ +bool kdesvnfilelist::refreshItem(FileListViewItem*item) +{ + if (!item) { + return false; + } + try { + item->setStat(svnclient()->singleStatus(item->fullName(),false,m_pList->m_remoteRevision)); + } catch (const svn::ClientException&e) { + item->setStat(new svn::Status()); + return false; + } + return true; +} + + +/*! + \fn kdesvnfilelist::slotCheckUpdates() + */ +void kdesvnfilelist::slotCheckUpdates() +{ + m_SvnWrapper->createUpdateCache(baseUri()); +} + +/*! + \fn kdesvnfilelist::reinitItems(FileListViewItem*_item = 0) + */ +void kdesvnfilelist::reinitItems(FileListViewItem*_item) +{ + FileListViewItem*item; + if (_item) { + item = _item; + } else { + item = static_cast<FileListViewItem*>(firstChild()); + } + if (!item) { + return; + } + item->init(); + if (item->childCount()==0 && item->isOpen()) { + m_Dirsread[item->fullName()]=false;; + setEnabled(false); + slotItemRead(item); + setEnabled(true); + } else { + item = static_cast<FileListViewItem*>(item->firstChild()); + while(item) { + reinitItems(item); + item = static_cast<FileListViewItem*>(item->nextSibling()); + } + } +} + + +/*! + \fn kdesvnfilelist::slotInfo() + */ +void kdesvnfilelist::slotInfo() +{ + QPtrList<SvnItem> lst; + SelectionList(&lst); + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + if (!isWorkingCopy()) { + rev = m_pList->m_remoteRevision; + } + if (lst.count()==0) { + if (!isWorkingCopy()) { + m_SvnWrapper->makeInfo(baseUri(),rev,svn::Revision::UNDEFINED,Kdesvnsettings::info_recursive()); + } else { + lst.append(SelectedOrMain()); + } + } + if (lst.count()>0) { + m_SvnWrapper->makeInfo(lst,rev,rev,Kdesvnsettings::info_recursive()); + } +} + + +/*! + \fn kdesvnfilelist::slotDirItemCreated(const QString&) + */ +void kdesvnfilelist::slotDirItemCreated(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->dirItems[what]='C'; + kdDebug()<<"slotDirItemCreated "<<what<<endl; + m_pList->startDirTimer(); +} + + +void kdesvnfilelist::updateParents(FileListViewItem*item) +{ + if (!item || !item->parent()) return; + FileListViewItem*it = static_cast<FileListViewItem*>(item->parent()); + it->update(); + updateParents(it); +} + +/*! + \fn kdesvnfilelist::slotDirItemDirty(const QString&) + */ +void kdesvnfilelist::slotDirItemDirty(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->dirItems[what]='M'; + m_pList->startDirTimer(); +} + +void kdesvnfilelist::_propListTimeout() +{ + dispProperties(false); +} + +void kdesvnfilelist::slotDisplayProperties() +{ + dispProperties(true); +} + +void kdesvnfilelist::dispProperties(bool force) +{ + CursorStack a(Qt::BusyCursor); + bool cache_Only = (!force && isNetworked() && !Kdesvnsettings::properties_on_remote_items()); + svn::PathPropertiesMapListPtr pm; + SvnItem*k = singleSelected(); + if (!k || !k->isRealVersioned()) { + emit sigProplist(svn::PathPropertiesMapListPtr(),false,QString("")); + return; + } + kdDebug()<<"Cacheonly: "<<cache_Only<<endl; + svn::Revision rev(isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision); + pm =m_SvnWrapper->propList(k->fullName(),rev,cache_Only); + emit sigProplist(pm,isWorkingCopy(),k->fullName()); +} + +void kdesvnfilelist::_dirwatchTimeout() +{ + kdDebug()<<"dirtimer"<<endl; + QMap<QString,QChar>::Iterator it; + m_pList->m_fileTip->setItem(0); + viewport()->setUpdatesEnabled(false); + bool repaintit=false; + for (it=m_pList->dirItems.begin();it!=m_pList->dirItems.end();++it) + { + QString what = it.key(); + QChar c = it.data(); + FileListViewItem*item = findEntryItem(what); + if (!item) { + m_pList->m_DirWatch->removeDir(what); + m_pList->m_DirWatch->removeFile(what); + m_SvnWrapper->deleteFromModifiedCache(what); + continue; + } + if (c == 'M') { + if (!item->isNormal() && item->isRealVersioned()) { + m_SvnWrapper->addModifiedCache(item->stat()); + } else { + m_SvnWrapper->deleteFromModifiedCache(what); + } + if (item->isDir()) { + if (item->isRealVersioned()) { + repaintit = refreshRecursive(item,false); + } else { + QListViewItem *_s; + while ( (_s=item->firstChild())) + { + delete _s; + } + checkUnversionedDirs(item); + } + } + updateParents(static_cast<FileListViewItem*>(item->parent())); + } else if (c=='D') { + if (item->isDir()) { + m_pList->m_DirWatch->removeDir(what); + } else { + m_pList->m_DirWatch->removeFile(what); + } + if (item->isDeleted()) { + m_SvnWrapper->addModifiedCache(item->stat()); + } else if (!item->isMissing()) { + QFileInfo fi(what); + if (!fi.exists()) { + FileListViewItem*p = static_cast<FileListViewItem*>(item->parent()); + delete item; + repaintit=true; + item = 0; + if (p && p->isVersioned()) { + p->update(); + updateParents(p); + } + } + } + } +#if 0 + when add dirItemDirty is send for folder above so no need for checking add-flag. + else { + kdDebug()<<"Entry added: "<<what << endl; + } +#endif + if (item) { + refreshItem(item); + } + } + m_pList->dirItems.clear(); + viewport()->setUpdatesEnabled(true); + if (repaintit) { +// viewport()->repaint(); + } +} + +/*! + \fn kdesvnfilelist::slotDirItemDeleted(const QString&) + */ +void kdesvnfilelist::slotDirItemDeleted(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->m_fileTip->setItem(0); + QMap<QString,QChar>::Iterator it = m_pList->dirItems.find(what); + if (it!=m_pList->dirItems.end() && m_pList->dirItems[what]=='A') { + m_pList->dirItems.erase(it); + } else { + m_pList->dirItems[what]='D'; + } + m_pList->startDirTimer(); +} + + +void kdesvnfilelist::gotPreview( const KFileItem*, const QPixmap&) +{ +#if 0 + FileListViewItem*which = findEntryItem(item->localPath()); + if (which) { + which->setPreviewPix(pixmap); + } +// m_previewJob = 0; +// if (m_svnitem || item != m_svnitem->fileItem()) return; + +// m_iconLabel -> setPixmap(pixmap); +#endif +} + +void kdesvnfilelist::gotPreviewResult() +{ +// m_previewJob = 0; +} + +FileListViewItem* kdesvnfilelist::findEntryItem(const QString&what,FileListViewItem*startAt) +{ + if (!startAt && !what.startsWith(baseUri())) return 0; + QString _what = what; + FileListViewItem*_s,*_temp; + if (!startAt) { + while (_what.endsWith("/")) { + _what.truncate(_what.length()-1); + } + _s = static_cast<FileListViewItem*>(firstChild()); + } else { + _s = static_cast<FileListViewItem*>(startAt->firstChild()); + } + _temp = 0; + while (_s) { + if (_s->fullName()==_what) { + return _s; + } + if (_what.startsWith(_s->fullName())) { + _temp = findEntryItem(_what,_s); + if (_temp) { + return _temp; + } + } + _s = static_cast<FileListViewItem*>(_s->nextSibling()); + } + return 0; +} + + +/*! + \fn kdesvnfilelist::contentsMouseMoveEvent( QMouseEvent *e ) + */ +void kdesvnfilelist::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if (!m_pList->mousePressed) + { + if (Kdesvnsettings::display_file_tips()) { + + QPoint vp = contentsToViewport( e->pos() ); + FileListViewItem*item = isExecuteArea( vp ) ? static_cast<FileListViewItem*>(itemAt( vp )) : 0L; + + if (item) { + vp.setY( itemRect( item ).y() ); + QRect rect( viewportToContents( vp ), QSize(20, item->height()) ); + m_pList->m_fileTip->setItem( static_cast<SvnItem*>(item), rect, item->pixmap(0)); + m_pList->m_fileTip->setPreview(KGlobalSettings::showFilePreview(item->fullName())/*&&isWorkingCopy()*/ + &&Kdesvnsettings::display_previews_in_file_tips()); + setShowToolTips(false); + } else { + m_pList->m_fileTip->setItem(0); + setShowToolTips(true); + } + } else { + m_pList->m_fileTip->setItem(0); + setShowToolTips(true); + } + } + else + { + if (( m_pList->presspos - e->pos() ).manhattanLength() > QApplication::startDragDistance()) + { + m_pList->m_fileTip->setItem(0); + m_pList->mousePressed=false; + //beginDrag(); + } + } + KListView::contentsMouseMoveEvent( e ); +} + +void kdesvnfilelist::contentsMousePressEvent(QMouseEvent*e) +{ + KListView::contentsMousePressEvent(e); + m_pList->m_fileTip->setItem(0); + QPoint p(contentsToViewport( e->pos())); + QListViewItem *i = itemAt( p ); + // this is from qt the example - hopefully I got my problems with drag&drop fixed. + if ( i ) { + // if the user clicked into the root decoration of the item, don't try to start a drag! + if ( p.x() > header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( i->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() || + p.x() < header()->cellPos( header()->mapToActual( 0 ) ) ) + { + m_pList->presspos = e->pos(); + m_pList->mousePressed = true; + } + } +} + +void kdesvnfilelist::contentsMouseReleaseEvent(QMouseEvent*e) +{ + KListView::contentsMouseReleaseEvent(e); + m_pList->mousePressed = false; +} + +/*! + \fn kdesvnfilelist::contentsWheelEvent( QWheelEvent * e ) + */ +void kdesvnfilelist::contentsWheelEvent( QWheelEvent * e ) +{ + // when scrolling with mousewheel, stop possible pending filetip + m_pList->m_fileTip->setItem(0); + KListView::contentsWheelEvent( e ); +} + +void kdesvnfilelist::leaveEvent(QEvent*e) +{ + m_pList->m_fileTip->setItem( 0 ); + KListView::leaveEvent( e ); +} + +void kdesvnfilelist::slotSettingsChanged() +{ + m_pList->m_fileTip->setOptions(!isNetworked()&&Kdesvnsettings::display_file_tips()&& + QToolTip::isGloballyEnabled(),true,6); + if (m_pList->reReadSettings()) { + refreshCurrentTree(); + } else { + viewport()->repaint(); + } + enableActions(); + sort(); + if (m_SvnWrapper && !m_SvnWrapper->doNetworking()) { + m_SvnWrapper->stopFillCache(); + } +} + + +/*! + \fn kdesvnfilelist::slotRelocate() + */ +void kdesvnfilelist::slotRelocate() +{ + if (!isWorkingCopy()) return; + SvnItem*k = SelectedOrMain(); + if (!k) { + KMessageBox::error(0,i18n("Error getting entry to relocate")); + return; + } + QString path,fromUrl; + path = k->fullName(); + fromUrl = k->Url(); + CheckoutInfo_impl*ptr; + KDialogBase * dlg = createDialog(&ptr,i18n("Relocate path %1").arg(path),true,"relocate_dlg"); + if (dlg) { + ptr->setStartUrl(fromUrl); + ptr->disableAppend(true); + ptr->disableTargetDir(true); + ptr->disableRange(true); + ptr->disableOpen(true); + ptr->disableExternals(true); + ptr->hideDepth(true,true); + bool done = false; + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"relocate_dlg")); + if (dlg->exec()==QDialog::Accepted) { + done = m_SvnWrapper->makeRelocate(fromUrl,ptr->reposURL(),path,ptr->overwrite()); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"relocate_dlg",false); + delete dlg; + if (!done) return; + } + refreshItem(k->fItem()); +} + +void kdesvnfilelist::checkUnversionedDirs( FileListViewItem * _parent ) +{ + QDir d; + if (_parent) + d.setPath(_parent->fullName()); //FIXME: this one is not reliable, what if _parent == 0?? + // else + // d.setPath(this->firstChild()->fullName()); + + d.setFilter( QDir::Files | QDir::Dirs ); + + const QFileInfoList *list = d.entryInfoList(); + if (!list) { + return; + } + QFileInfoListIterator nonversioned_it( *list ); + QFileInfo *fi; + + svn::StatusEntries nonversioned_list; + + // FIXME: create a dlist and feed to insertDirs, mean while .. we are copying insertDirs since we weren't able to set svn_node_kind into appropriate value + while ( (fi = nonversioned_it.current()) != 0 ) { + if ((fi->fileName()!=".") && (fi->fileName()!="..")) { + // trying to set entry->kind +// svn_wc_status2_t wc_stat; +// svn_wc_entry_t entry; +// char *temp; +// strcpy(temp, fi->fileName()); +// entry.name = temp; +// +// wc_stat.entry = &entry; +// if (fi->isDir()) +// entry.kind = svn_node_dir; +// else +// entry.kind = svn_node_file; +// +// svn::Status stat(fi->fileName(), &wc_stat); + + svn::StatusPtr stat(new svn::Status(fi->absFilePath())); + + // start copying insertDirs + FileListViewItem * item; + if (!_parent) { + item = new FileListViewItem(this, stat); + kdDebug()<< "creating new FileListViewitem " + item->fullName() << endl; + } else { + item = new FileListViewItem(this,_parent, stat); + kdDebug()<< "creating new FileListViewitem (with parent) " + item->fullName() << endl; + } + if (fi->isDir()) { + m_Dirsread[item->fullName()]=false; + item->setDropEnabled(true); + if (isWorkingCopy()) { + m_pList->m_DirWatch->addDir(item->fullName()); + } + kdDebug()<< "Watching folder: " + item->fullName() << endl; + } else if (isWorkingCopy()) { + m_pList->m_DirWatch->addFile(item->fullName()); + kdDebug()<< "Watching file: " + item->fullName() << endl; + } + // end of copying insertDirs + + nonversioned_list.append(stat); + kdDebug() << "creating new FileListViewItem from QDir entry: " << fi->fileName() << endl; + } + ++nonversioned_it; + } + + // uncomment this if you've ben able to set svn_node_kind (see above) + //this->insertDirs(_parent, nonversioned_list); +} + +void kdesvnfilelist::rescanIconsRec(FileListViewItem*startAt,bool checkNewer,bool no_update) +{ + FileListViewItem*_s; + if (!startAt) { + _s = static_cast<FileListViewItem*>(firstChild()); + } else { + _s = static_cast<FileListViewItem*>(startAt->firstChild()); + } + if (!_s) { + return; + } + svn::SharedPointer<svn::Status> d; + while (_s) { + //_s->makePixmap(); + + if (!no_update) { + if (m_SvnWrapper->getUpdated(_s->stat()->path(),d) && d) { + _s->updateStatus(d); + } else { + _s->update(); + } + } + rescanIconsRec(_s,checkNewer,no_update); + if (checkNewer && _s->isDir() && _s->isOpen()) { + svn::StatusEntries target; + m_SvnWrapper->getaddedItems(_s->stat()->path(),target); + insertDirs(_s,target); + } + _s = static_cast<FileListViewItem*>(_s->nextSibling()); + } +} + +void kdesvnfilelist::slotRescanIcons(bool checkNewer) +{ + rescanIconsRec(0L,checkNewer); +} + + +/*! + \fn kdesvnfilelist::slotCheckNewItems() + */ +void kdesvnfilelist::slotCheckNewItems() +{ + if (!isWorkingCopy()) { + KMessageBox::sorry(0,i18n("Only in working copy possible."),i18n("Error")); + return; + } + if (allSelected()->count()>1) { + KMessageBox::sorry(0,i18n("Only on single folder possible"),i18n("Error")); + return; + } + SvnItem*w = SelectedOrMain(); + if (!w) { + KMessageBox::sorry(0,i18n("Sorry - internal error!"),i18n("Error")); + return; + } + m_SvnWrapper->checkAddItems(w->fullName(),true); +} + +/*! + \fn kdesvnfilelist::slotMakeRangeLog() + */ +void kdesvnfilelist::slotMakeRangeLog() +{ + QString what; + SvnItem*k = SelectedOrMain(); + if (k) { + what = k->fullName(); + } else if (!isWorkingCopy() && allSelected()->count()==0){ + what = baseUri(); + } else { + return; + } + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + bool list = Kdesvnsettings::self()->log_always_list_changed_files(); + int i = dlg->exec(); + if (i==QDialog::Accepted) { + Rangeinput_impl::revision_range r = rdlg->getRange(); + m_SvnWrapper->makeLog(r.first,r.second,(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision), what,list,0); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); +} + + +void kdesvnfilelist::slotMakeTree() +{ + QString what; + SvnItem*k = SelectedOrMain(); + if (k) { + what = k->fullName(); + } else if (!isWorkingCopy() && allSelected()->count()==0){ + what = baseUri(); + } else { + return; + } + svn::Revision rev(isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision); + + m_SvnWrapper->makeTree(what,rev); +} + +void kdesvnfilelist::slotMakePartTree() +{ + QString what; + SvnItem*k = SelectedOrMain(); + if (k) { + what = k->fullName(); + } else if (!isWorkingCopy() && allSelected()->count()==0){ + what = baseUri(); + } else { + return; + } + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + int i = dlg->exec(); + Rangeinput_impl::revision_range r; + if (i==QDialog::Accepted) { + r = rdlg->getRange(); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + + if (i==QDialog::Accepted) { + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + m_SvnWrapper->makeTree(what,rev,r.first,r.second); + } +} + +/*! + \fn kdesvnfilelist::slotMakeLog() + */ +void kdesvnfilelist::slotMakeLog() +{ + QString what; + SvnItem*k = SelectedOrMain(); + if (k) { + what = k->fullName(); + } else if (!isWorkingCopy() && allSelected()->count()==0){ + what = baseUri(); + } else { + return; + } + // yes! so if we have a limit, the limit counts from HEAD + // not from START + svn::Revision start(svn::Revision::HEAD); + if (!isWorkingCopy()) { + start=m_pList->m_remoteRevision; + } + svn::Revision end(svn::Revision::START); + bool list = Kdesvnsettings::self()->log_always_list_changed_files(); + int l = Kdesvnsettings::self()->maximum_displayed_logs(); + m_SvnWrapper->makeLog(start,end,(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision),what,list,l); +} + +const svn::Revision& kdesvnfilelist::remoteRevision()const +{ + return m_pList->m_remoteRevision; +} + + +/*! + \fn kdesvnfilelist::slotOpenWith() + */ +void kdesvnfilelist::slotOpenWith() +{ + FileListViewItem* which = singleSelected(); + if (!which||which->isDir()) { + return; + } + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + KURL::List lst; + lst.append(which->kdeName(rev)); + KRun::displayOpenWithDialog(lst); +} + +void kdesvnfilelist::slotUnfoldTree() +{ + StopSimpleDlg sdlg(0,0,i18n("Unfold tree"),i18n("Unfold all folder")); + + connect(this,SIGNAL(sigListError()), + &sdlg,SLOT(makeCancel())); + + QListViewItemIterator it(this); + QTime t;t.start(); + + setUpdatesEnabled(false); + { + WidgetBlockStack a(this); + while (QListViewItem* item = it.current()) + { + if (item->isExpandable()) { + if (sdlg.isCanceld()) { + m_SvnWrapper->slotCancel(true); + break; + } + if (t.elapsed()>=200) { + sdlg.slotTick(); + kapp->processEvents(20); + t.restart(); + } + ((FileListViewItem*)item)->setOpenNoBlock(true); + } + ++it; + } + } + setFocus(); + setUpdatesEnabled(true); + viewport()->repaint(); + repaint(); + m_SvnWrapper->slotCancel(false); +} + +void kdesvnfilelist::slotFoldTree() +{ + QListViewItemIterator it(this); + while (QListViewItem* item = it.current()) + { + // don't close the top level directory + if (item->isExpandable() && item->parent()) + item->setOpen(false); + + ++it; + } +} + +/*! + \fn kdesvnfilelist::uniqueSelected() + */ +bool kdesvnfilelist::uniqueTypeSelected() +{ + FileListViewItemList*ls = allSelected(); + FileListViewItemListIterator it(*ls); + FileListViewItem*cur=it.current(); + if (!cur) { + return false; + } + bool dir = cur->isDir(); + while ( (cur=it.current())!=0) { + ++it; + if (cur->isDir()!=dir) { + return false; + } + } + return true; +} + +void kdesvnfilelist::slotChangeProperties(const svn::PropertiesMap&pm,const QValueList<QString>&dellist,const QString&path) +{ + m_SvnWrapper->changeProperties(pm,dellist,path); + FileListViewItem* which = singleSelected(); + kdDebug()<<(which?which->fullName():"nix") << " -> " << path<<endl; + if (which && which->fullName()==path) { + which->refreshStatus(); + refreshCurrent(which); + _propListTimeout(); + } +} + +void kdesvnfilelist::slotUpdateLogCache() +{ + if (baseUri().length()>0 && m_SvnWrapper->doNetworking()) { + KAction*temp = filesActions()->action("update_log_cache"); + + if (!m_SvnWrapper->threadRunning(SvnActions::fillcachethread)) { + m_SvnWrapper->startFillCache(baseUri()); + if (temp) { + temp->setText(i18n("Stop updating the logcache")); + } + } else { + m_SvnWrapper->stopFillCache(); + if (temp) { + temp->setText(i18n("Update log cache")); + } + } + } +} + +#include "kdesvnfilelist.moc" diff --git a/src/svnfrontend/kdesvnfilelist.h b/src/svnfrontend/kdesvnfilelist.h new file mode 100644 index 0000000..55ac7d3 --- /dev/null +++ b/src/svnfrontend/kdesvnfilelist.h @@ -0,0 +1,243 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KDESVNFILELIST_H +#define KDESVNFILELIST_H + +#include "itemdisplay.h" +#include "filelistviewitem.h" +#include "src/svnqt/status.hpp" +#include "src/svnqt/client.hpp" + +#include <klistview.h> +#include <kurl.h> +#include <ktrader.h> +#include <qmap.h> +#include <qptrlist.h> +#include <qevent.h> + +class KAction; +class KActionMenu; +class KActionCollection; +class KDialog; +class KDialogBase; +class KdesvnFileListPrivate; +class SvnActions; + +namespace KIO { + class Job; +} + +namespace svn { + class Revision; +} +/** +@author Rajko Albrecht +*/ +class kdesvnfilelist : public KListView,public ItemDisplay +{ + Q_OBJECT + friend class FileListViewItem; +public: + kdesvnfilelist(KActionCollection*,QWidget *parent = 0, const char *name = 0); + virtual ~kdesvnfilelist(); + + virtual bool openURL( const KURL &url,bool noReinit=false ); + virtual SvnItem*SelectedOrMain(); + virtual SvnItem*Selected(); + virtual void SelectionList(SvnItemList*target); + + virtual QWidget*realWidget(); + + KActionCollection*filesActions(); + bool refreshItem(FileListViewItem*); + +protected: + const svn::Revision& remoteRevision()const; + bool m_deletePerfect; + QMap<QString,bool> m_Dirsread; + + KActionCollection* m_filesAction; + KAction*m_BlameAction,*m_BlameRangeAction,*m_CatAction,*m_MkdirAction; + KAction*m_InfoAction,*m_commitAction,*m_UpdateHead,*m_UpdateRev; + KAction*m_AddCurrent,*m_DelCurrent,*m_CheckoutAction,*m_CheckoutCurrentAction,*m_RevertAction; + KAction*m_changeToRepository,*m_switchRepository,*m_ExportAction,*m_ExportCurrentAction; + KAction*m_CleanupAction,*m_ResolvedAction,*m_ImportDirsIntoCurrent,*m_RefreshViewAction,*m_MergeRevisionAction; + KAction*m_RenameAction,*m_CopyAction; + KAction*m_LockAction,*m_UnlockAction,*m_IgnoreAction; + + SvnActions*m_SvnWrapper; + + /* the parent entry must removed from list before */ + void insertDirs(FileListViewItem * _parent,svn::StatusEntries&); + bool checkDirs(const QString&,FileListViewItem * _parent); + void setupActions(); + svn::Client*svnclient(); + + + FileListViewItem* singleSelected(); + FileListViewItemList* allSelected(); + + template<class T> KDialogBase* createDialog(T**ptr, + const QString&_head, + bool OkCancel=false, + const char*name="dialog", + bool showHelp=false + ); + + FileListViewItemList* m_SelectedItems; + FileListViewItem* findEntryItem(const QString&,FileListViewItem*startAt=0); + + virtual bool refreshRecursive(FileListViewItem*,bool down=true); + virtual void updateParents(FileListViewItem*); + virtual void checkUnversionedDirs( FileListViewItem * _parent ); + + /** + * Overridden virtuals for Qt drag 'n drop (XDND) + */ + virtual void contentsDragEnterEvent( QDragEnterEvent* ); + virtual void contentsDragLeaveEvent( QDragLeaveEvent* ); + virtual void contentsDragMoveEvent( QDragMoveEvent* ); + virtual void contentsDropEvent( QDropEvent* ); + virtual bool acceptDrag(QDropEvent *event)const; + //virtual void startDrag(); + virtual QDragObject* dragObject(); + + void dispDummy(); + void reinitItems(FileListViewItem*_item = 0); + KURL::List selectedUrls(); + + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + virtual void contentsMousePressEvent(QMouseEvent*e); + virtual void contentsMouseReleaseEvent(QMouseEvent*e); + virtual void contentsWheelEvent( QWheelEvent * e ); + virtual void leaveEvent(QEvent*e); + virtual void rescanIconsRec(FileListViewItem*_parent=0,bool checkNewer=false,bool no_update=false); + + KTrader::OfferList offersList(SvnItem*item,bool execOnly=false); + +private: + KdesvnFileListPrivate*m_pList; + void cleanHighLighter(); + bool validDropEvent(QDropEvent*event,QListViewItem*&item); + void copy_move(bool move); + +protected slots: + virtual void slotSelectBrowsingRevision(); + virtual void slotItemRead(QListViewItem*); + virtual void slotContextMenuRequested(QListViewItem *, const QPoint &, int); + virtual void slotSelectionChanged(); + virtual void slotClientException(const QString&); + virtual void slotNotifyMessage(const QString&); + virtual void slotDirAdded(const QString&,FileListViewItem*); + virtual void slotReinitItem(SvnItem*); + virtual void slotItemDoubleClicked(QListViewItem*); + virtual void slotImportIntoCurrent(bool); + virtual void slotImportDirsIntoCurrent(); + virtual void slotImportIntoDir(const KURL&,const QString&,bool); + + /* subversion slots */ + virtual void slotChangeToRepository(); + virtual void slotCleanupAction(); + virtual void slotResolved(); + virtual void slotTryResolve(); + virtual void slotMergeRevisions(); + virtual void slotMerge(); + virtual void slotDropped(QDropEvent *,QListViewItem*); + virtual void viewportPaintEvent(QPaintEvent *); + virtual void slotRename(); + virtual void slotCopy(); + virtual void slotCat(); + virtual void slotDelete(); + virtual void slotDisplayLastDiff(); + + /* callback slots */ + virtual void slotCopyFinished( KIO::Job *); + virtual void slotDeleteFinished(KIO::Job*); + virtual void _openURL(const QString&); + virtual void _dirwatchTimeout(); + virtual void _propListTimeout(); + + /* internal slots */ + virtual void readSupportData(); + virtual void slotUpdateLogCache(); + + virtual void enableActions(); + +signals: + void sigLogMessage(const QString&); + void changeCaption(const QString&); + void sigShowPopup(const QString&,QWidget**); + void sigUrlOpend(bool); + void sigSwitchUrl(const KURL&); + void sigUrlChanged(const QString&); + void sigProplist(const svn::PathPropertiesMapListPtr&,bool,const QString&); + void sigListError(); + void sigCacheStatus(Q_LONG,Q_LONG); + +public slots: + virtual void refreshCurrentTree(); + virtual void refreshCurrent(SvnItem*); + virtual void closeMe(); + virtual void slotMkdir(); + virtual void slotMkBaseDirs(); + virtual void slotSettingsChanged(); + virtual void slotChangeProperties(const svn::PropertiesMap&,const QValueList<QString>&,const QString&); + + +protected slots: + virtual void slotLock(); + virtual void slotUnlock(); + virtual void slotIgnore(); + virtual void slotBlame(); + virtual void slotRangeBlame(); + virtual void slotSimpleHeadDiff(); + virtual void slotSimpleBaseDiff(); + + virtual void slotDiffRevisions(); + virtual void slotDiffPathes(); + virtual void slotRevisionCat(); + virtual void slotCheckUpdates(); + virtual void slotInfo(); + virtual void slotDirItemCreated(const QString&); + virtual void slotDirItemDirty(const QString&); + virtual void slotDirItemDeleted(const QString&); + virtual void slotRelocate(); + virtual void slotRescanIcons(bool); + virtual void slotCheckNewItems(); + virtual void slotMakeRangeLog(); + virtual void slotMakeLog(); + virtual void slotMakeTree(); + virtual void slotMakePartTree(); + virtual void slotInternalDrop(); + virtual void slotOpenWith(); + virtual void slotDisplayProperties(); + + virtual void slotUnfoldTree(); + virtual void slotFoldTree(); + +private slots: + void gotPreview( const KFileItem*, const QPixmap& ); + void gotPreviewResult(); +protected: + virtual bool uniqueTypeSelected(); + virtual void dispProperties(bool); +}; + +#endif diff --git a/src/svnfrontend/keystatus.cpp b/src/svnfrontend/keystatus.cpp new file mode 100644 index 0000000..5e6a324 --- /dev/null +++ b/src/svnfrontend/keystatus.cpp @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "keystatus.h" + +#include <qwidget.h> +#include <X11/Xlib.h> + +void KeyState::keystate(int*root_x,int*root_y,int*win_x,int*win_y,unsigned int*keybstate) +{ + Window root; + Window child; + unsigned int kstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + root_x, root_y, win_x, win_y, &kstate); + *keybstate=0; + if (kstate&ControlMask) { + *keybstate|=Qt::ControlButton; + } + if (kstate&ShiftMask) { + *keybstate|=Qt::ShiftButton; + } +} diff --git a/src/svnfrontend/keystatus.h b/src/svnfrontend/keystatus.h new file mode 100644 index 0000000..75fd3a9 --- /dev/null +++ b/src/svnfrontend/keystatus.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _KEYSTATUS_H +#define _KEYSTATUS_H + +class KeyState +{ +public: + KeyState(){} + ~KeyState(){} + static void keystate(int*,int*,int*,int*,unsigned int*mask); + +}; + +#endif + diff --git a/src/svnfrontend/loaddmpdlg.ui b/src/svnfrontend/loaddmpdlg.ui new file mode 100644 index 0000000..5c22cee --- /dev/null +++ b/src/svnfrontend/loaddmpdlg.ui @@ -0,0 +1,183 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>LoadDmpDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>LoadDmpDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>343</width> + <height>272</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Load into folder:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="toolTip" stdset="0"> + <string>Path to load the dump into (see contexthelp)</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If not empty, load the dump into a specific folder instead into root of repository. This folder must exist before loading the dump.</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Dump file:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_Dumpfile</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Load into repository:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>m_Rootfolder</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>Path to load the dump into (see contexthelp)</string> + </property> + <property name="whatsThis" stdset="0"> + <string>If not empty, load the dump into a specific folder instead into root of repository. This folder must exist before loading the dump.</string> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>m_Repository</cstring> + </property> + <property name="mode"> + <number>18</number> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>m_UuidGroup</cstring> + </property> + <property name="title"> + <string>Uuid action</string> + </property> + <property name="toolTip" stdset="0"> + <string>How to handle UUIDs</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The repository's UUID will be updated if the dumpstream contains a UUID and action isn't set to ignore and either the repository contains no revisions or action is set to force. If the dump contains no UUID than this action is ignored.</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_UUidDefault</cstring> + </property> + <property name="text"> + <string>Default</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_UUidIgnore</cstring> + </property> + <property name="text"> + <string>Ignore</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_UUidForce</cstring> + </property> + <property name="text"> + <string>Force</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </vbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_UsePre</cstring> + </property> + <property name="text"> + <string>Use pre-commit hook</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_UsePost</cstring> + </property> + <property name="text"> + <string>Use post-commit hook</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/loaddmpdlg_impl.cpp b/src/svnfrontend/loaddmpdlg_impl.cpp new file mode 100644 index 0000000..63954a2 --- /dev/null +++ b/src/svnfrontend/loaddmpdlg_impl.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "loaddmpdlg_impl.h" + +#include <qpushbutton.h> +#include <qlabel.h> +#include <kurlrequester.h> +#include <klineedit.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qcheckbox.h> + +LoadDmpDlg_impl::LoadDmpDlg_impl(QWidget *parent, const char *name) + :LoadDmpDlg(parent, name) +{ +} + +LoadDmpDlg_impl::~LoadDmpDlg_impl() +{ +} + +/*! + \fn LoadDmpDlg_impl::usePost()const + */ +bool LoadDmpDlg_impl::usePost()const +{ + return m_UsePost->isChecked(); +} + + +/*! + \fn LoadDmpDlg_impl::usePre()const + */ +bool LoadDmpDlg_impl::usePre()const +{ + return m_UsePre->isChecked(); +} + + +/*! + \fn LoadDmpDlg_impl::uuidAction()const + */ +int LoadDmpDlg_impl::uuidAction()const +{ + return m_UuidGroup->selectedId(); +} + + +/*! + \fn LoadDmpDlg_impl::dumpFile()const + */ +QString LoadDmpDlg_impl::dumpFile()const +{ + KURL u = m_Dumpfile->url(); + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + + +/*! + \fn LoadDmpDlg_impl::repository()const + */ +QString LoadDmpDlg_impl::repository()const +{ + KURL u = m_Repository->url(); + QString res = u.path(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + + +/*! + \fn LoadDmpDlg_impl::parentPath()const + */ +QString LoadDmpDlg_impl::parentPath()const +{ + QString res = m_Rootfolder->text(); + while (res.endsWith("/")) { + res.truncate(res.length()-1); + } + return res; +} + +#include "loaddmpdlg_impl.moc" diff --git a/src/svnfrontend/loaddmpdlg_impl.h b/src/svnfrontend/loaddmpdlg_impl.h new file mode 100644 index 0000000..fef0950 --- /dev/null +++ b/src/svnfrontend/loaddmpdlg_impl.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef LOADDMPDLG_IMPL_H +#define LOADDMPDLG_IMPL_H + +#include "loaddmpdlg.h" + +class LoadDmpDlg_impl: public LoadDmpDlg { +Q_OBJECT +public: + LoadDmpDlg_impl(QWidget *parent = 0, const char *name = 0); + virtual ~LoadDmpDlg_impl(); + bool usePost()const; + bool usePre()const; + int uuidAction()const; + QString dumpFile()const; + QString repository()const; + QString parentPath()const; + +public slots: +}; + +#endif diff --git a/src/svnfrontend/merge_dlg.ui b/src/svnfrontend/merge_dlg.ui new file mode 100644 index 0000000..f26179a --- /dev/null +++ b/src/svnfrontend/merge_dlg.ui @@ -0,0 +1,213 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MergeDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>MergeDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>397</width> + <height>239</height> + </rect> + </property> + <property name="caption"> + <string>MergeSettings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>m_SrcOneInput</cstring> + </property> + </widget> + <widget class="KURLRequester" row="1" column="1"> + <property name="name"> + <cstring>m_SrcTwoInput</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_SrcOneLabel</cstring> + </property> + <property name="text"> + <string>Source 1:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="KURLRequester" row="2" column="1"> + <property name="name"> + <cstring>m_OutInput</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_SrcTwoLabel</cstring> + </property> + <property name="text"> + <string>Source 2:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>m_OutLabel</cstring> + </property> + <property name="text"> + <string>Output to:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_ForceCheck</cstring> + </property> + <property name="text"> + <string>Force delete on modified/unversioned</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_RelatedCheck</cstring> + </property> + <property name="text"> + <string>Handle unrelated as related items</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>m_DryCheck</cstring> + </property> + <property name="text"> + <string>Just dry run without modifications</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>m_RecursiveCheck</cstring> + </property> + <property name="text"> + <string>Recursive</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="Rangeinput_impl"> + <property name="name"> + <cstring>m_RangeInput</cstring> + </property> + <property name="minimumSize"> + <size> + <width>40</width> + <height>40</height> + </size> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_useExternMerge</cstring> + </property> + <property name="text"> + <string>Use external merge not subversions merge</string> + </property> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>Rangeinput_impl</class> + <header location="local">rangeinput_impl.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <property type="Bool">StartOnly</property> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>m_useExternMerge</sender> + <signal>toggled(bool)</signal> + <receiver>MergeDlg</receiver> + <slot>externDisplayToggled(bool)</slot> + </connection> +</connections> +<slots> + <slot access="protected">externDisplayToggled(bool)</slot> +</slots> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>rangeinput_impl.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/mergedlg_impl.cpp b/src/svnfrontend/mergedlg_impl.cpp new file mode 100644 index 0000000..28bb02e --- /dev/null +++ b/src/svnfrontend/mergedlg_impl.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "mergedlg_impl.h" +#include "rangeinput_impl.h" +#include "src/svnqt/url.hpp" +#include "helpers/ktranslateurl.h" +#include "src/settings/kdesvnsettings.h" + +#include <kurlrequester.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <kdebug.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qvbox.h> + +MergeDlg_impl::MergeDlg_impl(QWidget *parent, const char *name,bool src1,bool src2,bool out) + :MergeDlg(parent, name) +{ + m_SrcOneInput->setMode(KFile::Directory|KFile::File); + if (!src1) { + m_SrcOneInput->setEnabled(false); + m_SrcOneInput->hide(); + m_SrcOneLabel->hide(); + } + m_SrcTwoInput->setMode(KFile::Directory|KFile::File); + if (!src2) { + m_SrcTwoInput->setEnabled(false); + m_SrcTwoInput->hide(); + m_SrcTwoLabel->hide(); + } + m_OutInput->setMode(KFile::LocalOnly|KFile::Directory|KFile::File); + if (!out) { + m_OutInput->setEnabled(false); + m_OutInput->hide(); + m_OutLabel->hide(); + } + adjustSize(); + setMinimumSize(minimumSizeHint()); + m_useExternMerge->setChecked(Kdesvnsettings::extern_merge_default()); +} + +MergeDlg_impl::~MergeDlg_impl() +{ +} + +void MergeDlg_impl::setSrc1(const QString&what) +{ + if (what.isEmpty()) { + m_SrcOneInput->setURL(""); + return; + } + KURL uri(what); + kdDebug()<<"What: "<<what << " URL: "<<uri<<endl; + if (uri.protocol()=="file") { + if (what.startsWith("file:")) { + uri.setProtocol("ksvn+file"); + } else { + uri.setProtocol(""); + } + } else { + uri.setProtocol(helpers::KTranslateUrl::makeKdeUrl(uri.protocol())); + } + m_SrcOneInput->setURL(uri.url()); +} + +void MergeDlg_impl::setSrc2(const QString&what) +{ + if (what.isEmpty()) { + m_SrcTwoInput->setURL(""); + return; + } + KURL uri(what); + if (uri.protocol()=="file") { + if (what.startsWith("file:")) { + uri.setProtocol("ksvn+file"); + } else { + uri.setProtocol(""); + } + } else { + uri.setProtocol(helpers::KTranslateUrl::makeKdeUrl(uri.protocol())); + } + m_SrcTwoInput->setURL(uri.url()); +} + +void MergeDlg_impl::setDest(const QString&what) +{ + if (what.isEmpty()) { + m_OutInput->setURL(""); + return; + } + KURL uri(what); + uri.setProtocol(""); + m_OutInput->setURL(uri.url()); +} + +bool MergeDlg_impl::recursive()const +{ + return m_RecursiveCheck->isChecked(); +} + +bool MergeDlg_impl::force()const +{ + return m_ForceCheck->isChecked(); +} + +bool MergeDlg_impl::ignorerelated()const +{ + return m_RelatedCheck->isChecked(); +} + +bool MergeDlg_impl::dryrun()const +{ + return m_DryCheck->isChecked(); +} + +bool MergeDlg_impl::useExtern()const +{ + return m_useExternMerge->isChecked(); +} + +QString MergeDlg_impl::Src1()const +{ + KURL uri(m_SrcOneInput->url()); + QString proto = svn::Url::transformProtokoll(uri.protocol()); + if (proto=="file"&&!m_SrcOneInput->url().startsWith("ksvn+file:")) { + uri.setProtocol(""); + } else { + uri.setProtocol(proto); + } + return uri.url(); +} + +QString MergeDlg_impl::Src2()const +{ + if (m_SrcTwoInput->url().isEmpty()) { + return ""; + } + KURL uri(m_SrcTwoInput->url()); + QString proto = svn::Url::transformProtokoll(uri.protocol()); + if (proto=="file"&&!m_SrcTwoInput->url().startsWith("ksvn+file:")) { + uri.setProtocol(""); + } else { + uri.setProtocol(proto); + } + return uri.url(); +} + +QString MergeDlg_impl::Dest()const +{ + KURL uri(m_OutInput->url()); + uri.setProtocol(""); + return uri.url(); +} + +Rangeinput_impl::revision_range MergeDlg_impl::getRange()const +{ + return m_RangeInput->getRange(); +} + + +/*! + \fn MergeDlg_impl::getMergeRange(bool*force,bool*recursive,bool*related,bool*dry) + */ +bool MergeDlg_impl::getMergeRange(Rangeinput_impl::revision_range&range,bool*force,bool*recursive,bool*ignorerelated,bool*dry, + bool*useExternal, + QWidget*parent,const char*name) +{ + MergeDlg_impl*ptr = 0; + KDialogBase dlg(parent,name,true,i18n("Enter merge range"), + KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Help, + KDialogBase::Ok,true); + dlg.setHelp("merging-items","kdesvn"); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + ptr = new MergeDlg_impl(Dialog1Layout,"merge_range_dlg",false,false,false); + dlg.resize( QSize(480,360).expandedTo(dlg.minimumSizeHint()) ); + if (dlg.exec()!=QDialog::Accepted) { + return false; + } + range = ptr->getRange(); + *force = ptr->force(); + *recursive=ptr->recursive(); + *ignorerelated=ptr->ignorerelated(); + *dry = ptr->dryrun(); + *useExternal = ptr->useExtern(); + return true; +} + +void MergeDlg_impl::externDisplayToggled(bool how) +{ + m_DryCheck->setEnabled(!how); + m_RelatedCheck->setEnabled(!how); + m_ForceCheck->setEnabled(!how); +} + +#include "mergedlg_impl.moc" diff --git a/src/svnfrontend/mergedlg_impl.h b/src/svnfrontend/mergedlg_impl.h new file mode 100644 index 0000000..90dc3d8 --- /dev/null +++ b/src/svnfrontend/mergedlg_impl.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef MERGEDLG_IMPL_H +#define MERGEDLG_IMPL_H + +#include "merge_dlg.h" +#include "rangeinput_impl.h" + +class MergeDlg_impl: public MergeDlg { +Q_OBJECT +public: + MergeDlg_impl(QWidget *parent = 0, const char *name = 0,bool src1=true,bool src2=true,bool out=true); + virtual ~MergeDlg_impl(); + + bool recursive()const; + bool force()const; + bool ignorerelated()const; + bool dryrun()const; + bool useExtern()const; + + QString Src1()const; + QString Src2()const; + QString Dest()const; + Rangeinput_impl::revision_range getRange()const; + + void setSrc1(const QString&); + void setSrc2(const QString&); + void setDest(const QString&); + + static bool getMergeRange(Rangeinput_impl::revision_range&range, + bool*force,bool*recursive,bool*ignorerelated,bool*dry,bool*useExternal,QWidget*parent=0,const char*name=0); +protected slots: + virtual void externDisplayToggled(bool); + +}; + +#endif diff --git a/src/svnfrontend/modifiedthread.cpp b/src/svnfrontend/modifiedthread.cpp new file mode 100644 index 0000000..f7f6c90 --- /dev/null +++ b/src/svnfrontend/modifiedthread.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "modifiedthread.h" +#include "tcontextlistener.h" + +#include "src/svnqt/svnqttypes.hpp" + +#include <qobject.h> +#include <kdebug.h> +#include <kapplication.h> + +CheckModifiedThread::CheckModifiedThread(QObject*_parent,const QString&what,bool _updates) + : QThread(),mutex(),m_ContextListener(0) +{ + m_Parent = _parent; + m_CurrentContext = new svn::Context(); + m_ContextListener = new ThreadContextListener(m_Parent); + QObject::connect(m_ContextListener,SIGNAL(sendNotify(const QString&)),m_Parent,SLOT(slotNotifyMessage(const QString&))); + + m_CurrentContext->setListener(m_ContextListener); + m_what = what; + m_Svnclient = svn::Client::getobject(m_CurrentContext,0); + m_updates = _updates; +} + +CheckModifiedThread::~CheckModifiedThread() +{ + m_CurrentContext->setListener(0); + delete m_Svnclient; + m_ContextListener=0; +} + +void CheckModifiedThread::cancelMe() +{ + // method is threadsafe! + m_ContextListener->setCanceled(true); +} + +const svn::StatusEntries&CheckModifiedThread::getList()const +{ + return m_Cache; +} + +void CheckModifiedThread::run() +{ + // what must be cleaned! + svn::Revision where = svn::Revision::HEAD; + QString ex; + try { + // rec all up noign + m_Cache = m_Svnclient->status(m_what,svn::DepthInfinity,false,m_updates,false,where); + } catch (const svn::Exception&e) { + m_ContextListener->contextNotify(e.msg()); + } + KApplication*k = KApplication::kApplication(); + if (k) { + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_FINISHED); + ev->setData((void*)this); + k->postEvent(m_Parent,ev); + } +} diff --git a/src/svnfrontend/modifiedthread.h b/src/svnfrontend/modifiedthread.h new file mode 100644 index 0000000..93028e8 --- /dev/null +++ b/src/svnfrontend/modifiedthread.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _MODIFIED_THREAD_H +#define _MODIFIED_THREAD_H + +#include "src/svnqt/client.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/status.hpp" +#include "ccontextlistener.h" +#include "eventnumbers.h" +#include "frontendtypes.h" + +#include <qthread.h> +#include <qevent.h> + +class QObject; + +class CheckModifiedThread:public QThread +{ +public: + CheckModifiedThread(QObject*,const QString&what,bool _updates=false); + virtual ~CheckModifiedThread(); + virtual void run(); + virtual void cancelMe(); + virtual const svn::StatusEntries&getList()const; + +protected: + QMutex mutex; + svn::Client* m_Svnclient; + svn::ContextP m_CurrentContext; + ThreadContextListenerP m_ContextListener; + QObject*m_Parent; + QString m_what; + bool m_updates; + svn::StatusEntries m_Cache; +}; + +#endif + diff --git a/src/svnfrontend/opencontextmenu.cpp b/src/svnfrontend/opencontextmenu.cpp new file mode 100644 index 0000000..796ac22 --- /dev/null +++ b/src/svnfrontend/opencontextmenu.cpp @@ -0,0 +1,83 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "opencontextmenu.h" + +#include <krun.h> +#include <klocale.h> + +OpenContextmenu::OpenContextmenu(const KURL&aPath,const KTrader::OfferList&aList,QWidget* parent, const char* name) + : QPopupMenu(parent, name),m_Path(aPath),m_List(aList) +{ + setup(); +} + +OpenContextmenu::~OpenContextmenu() +{ +} + +void OpenContextmenu::setup() +{ + m_mapPopup.clear(); + KTrader::OfferList::ConstIterator it = m_List.begin(); + int id = 1; + KAction*act; + for( ; it != m_List.end(); ++it ) { + if ((*it)->noDisplay()) + continue; + + QCString nam; + nam.setNum( id ); + + QString actionName( (*it)->name().replace("&", "&&") ); + act = new KAction( actionName, (*it)->pixmap( KIcon::Small ), 0, + this, SLOT( slotRunService() ), this, nam.prepend( "appservice_" ) ); + act->plug(this); + m_mapPopup[ id++ ] = *it; + } + if (m_List.count()>0) { + insertSeparator( ); + } + act = new KAction(i18n("Other..."),0, 0, + this, SLOT( slotOpenWith() ),this,"openwith"); + act->plug(this); +} + +void OpenContextmenu::slotRunService() +{ + QCString senderName = sender()->name(); + int id = senderName.mid( senderName.find( '_' ) + 1 ).toInt(); + + QMap<int,KService::Ptr>::Iterator it = m_mapPopup.find( id ); + if ( it != m_mapPopup.end() ) + { + KRun::run( **it, m_Path ); + return; + } + +} + +void OpenContextmenu::slotOpenWith() +{ + KURL::List lst; + lst.append(m_Path); + KRun::displayOpenWithDialog(lst); +} + +#include "opencontextmenu.moc" diff --git a/src/svnfrontend/opencontextmenu.h b/src/svnfrontend/opencontextmenu.h new file mode 100644 index 0000000..0ec106b --- /dev/null +++ b/src/svnfrontend/opencontextmenu.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef OPENCONTEXTMENU_H +#define OPENCONTEXTMENU_H + +#include <ktrader.h> +#include <kaction.h> +#include <kurl.h> +#include <qpopupmenu.h> +#include <qmap.h> + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class OpenContextmenu : public QPopupMenu +{ +Q_OBJECT +public: + OpenContextmenu(const KURL&,const KTrader::OfferList&,QWidget* parent, const char* name); + virtual ~OpenContextmenu(); +protected: + KURL m_Path; + KTrader::OfferList m_List; + QMap<int,KService::Ptr> m_mapPopup; + + void setup(); + +protected slots: + virtual void slotOpenWith(); + virtual void slotRunService(); +}; + +#endif diff --git a/src/svnfrontend/propertiesdlg.cpp b/src/svnfrontend/propertiesdlg.cpp new file mode 100644 index 0000000..4203765 --- /dev/null +++ b/src/svnfrontend/propertiesdlg.cpp @@ -0,0 +1,293 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "src/svnfrontend/fronthelpers/propertyitem.h" +#include "src/svnfrontend/fronthelpers/propertylist.h" +#include "propertiesdlg.h" +#include "editproperty_impl.h" +#include "svnitem.h" +#include "src/svnqt/client.hpp" + +#include <qvariant.h> +#include <qlabel.h> +#include <qheader.h> +#include <kpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kiconloader.h> +#include <kdebug.h> + +/* + * Constructs a PropertiesDlg as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +PropertiesDlg::PropertiesDlg(SvnItem*which, svn::Client*aClient, const svn::Revision&aRev, QWidget* parent, const char* name, bool modal) + : + KDialogBase(parent,name,modal,i18n("Modify properties"),Ok|Cancel/*|Help|User1|User2*/, Ok, + true/*, KStdGuiItem::add(),KStdGuiItem::remove() */), + m_Item(which),m_changed(false), + m_Client(aClient),m_Rev(aRev) +{ + if ( !name ) + setName( "PropertiesDlg" ); + QWidget * m = makeMainWidget(); + PropertiesDlgLayout = new QHBoxLayout(m, marginHint(), spacingHint(), "PropertiesDlgLayout"); + + m_PropertiesListview = new Propertylist(m, "m_PropertiesListview" ); + m_PropertiesListview->setAllColumnsShowFocus( TRUE ); + m_PropertiesListview->setShowSortIndicator( TRUE ); + m_PropertiesListview->setCommitchanges(false); + m_PropertiesListview->setItemsRenameable(true); + m_PropertiesListview->setRenameable(0,true); + m_PropertiesListview->setRenameable(1,true); + + m_PropertiesListview->setFullWidth( TRUE ); + PropertiesDlgLayout->addWidget( m_PropertiesListview); + + m_rightLayout = new QVBoxLayout(0, marginHint(), spacingHint(), "m_rightLayout"); + m_AddButton = new KPushButton(m, "m_AddButton" ); + m_rightLayout->addWidget( m_AddButton ); + m_ModifyButton = new KPushButton(m, "m_ModifyButton" ); + m_rightLayout->addWidget( m_ModifyButton ); + m_DeleteButton = new KPushButton(m, "m_DeleteButton" ); + m_rightLayout->addWidget( m_DeleteButton ); + m_rightSpacer = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding ); + m_rightLayout->addItem(m_rightSpacer); + PropertiesDlgLayout->addLayout(m_rightLayout); + m_DeleteButton->setEnabled(false); + m_ModifyButton->setEnabled(false); + + //PropertiesDlgLayout->addLayout(midLayout); + languageChange(); + clearWState( WState_Polished ); + + // signals and slots connections + connect( m_AddButton, SIGNAL(clicked()), this, SLOT(slotAdd())); + connect( m_ModifyButton, SIGNAL(clicked()), this, SLOT(slotModify())); + connect( m_DeleteButton, SIGNAL(clicked()), this, SLOT(slotDelete())); + connect(this,SIGNAL(helpClicked()),SLOT(slotHelp())); + connect(m_PropertiesListview,SIGNAL(selectionChanged(QListViewItem*)),this,SLOT(slotSelectionChanged(QListViewItem*))); +// connect(m_PropertiesListview,SIGNAL(executed(QListViewItem*)),this,SLOT(slotSelectionExecuted(QListViewItem*))); + + if (!m_Client) { + m_PropertiesListview->setEnabled(false); + } +} + +bool PropertiesDlg::hasChanged()const +{ + return m_changed; +} + +/* + * Destroys the object and frees any allocated resources + */ +PropertiesDlg::~PropertiesDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void PropertiesDlg::languageChange() +{ + setCaption( i18n("View and modify properties") ); + QToolTip::add(m_PropertiesListview, i18n( "List of properties set" )); + m_AddButton->setText(i18n("Add property")); + m_ModifyButton->setText(i18n("Modify property")); + m_DeleteButton->setText(i18n("Delete property")); +} + +void PropertiesDlg::slotHelp() +{ + qWarning( "PropertiesDlg::slotHelp(): Not implemented yet" ); +} + +void PropertiesDlg::slotSelectionChanged(QListViewItem*item) +{ + m_DeleteButton->setEnabled(item); + m_ModifyButton->setEnabled(item); + if (!item || item->rtti()!=PropertyListViewItem::_RTTI_) return; + PropertyListViewItem*ki = static_cast<PropertyListViewItem*> (item); + if (PropertyListViewItem::protected_Property(ki->currentName())) { + m_DeleteButton->setEnabled(false); + m_ModifyButton->setEnabled(false); + return; + } + if (ki->deleted()) { + m_DeleteButton->setText(i18n("Undelete property")); + } else { + m_DeleteButton->setText(i18n("Delete property")); + } +} + + + +/*! + \fn PropertiesDlg::initItem + */ +void PropertiesDlg::initItem() +{ + QString ex; + if (!m_Client) { + ex = i18n("Missing SVN link"); + emit clientException(ex); + return; + } + svn::Path what(m_Item->fullName()); + svn::PathPropertiesMapListPtr propList; + try { + propList = m_Client->proplist(what,m_Rev,m_Rev); + } catch (const svn::ClientException&e) { + emit clientException(e.msg()); + return; + } + m_PropertiesListview->displayList(propList,true,m_Item->fullName()); + initDone = true; +} + +/*! + \fn PropertiesDlg::exec() + */ +int PropertiesDlg::exec() +{ + return KDialogBase::exec(); +} + +void PropertiesDlg::polish() +{ + KDialogBase::polish(); + initItem(); +} + +/*! + \fn PropertiesDlg::slotSelectionExecuted(QListViewItem*) + */ +void PropertiesDlg::slotSelectionExecuted(QListViewItem*) +{ +} + +/*! + \fn PropertiesDlg::slotAdd() + */ +void PropertiesDlg::slotAdd() +{ + /// @TODO Use a object variable to store a reference to dlg for further reuse + EditProperty_impl dlg(this); + dlg.setDir(m_Item->isDir()); + if (dlg.exec()==QDialog::Accepted) { + if (PropertyListViewItem::protected_Property(dlg.propName())) { + KMessageBox::error(this,i18n("This property may not set by users.\nRejecting it."),i18n("Protected property")); + return; + } + if (m_PropertiesListview->checkExisting(dlg.propName())) { + KMessageBox::error(this,i18n("A property with that name exists.\nRejecting it."),i18n("Double property")); + return; + } + PropertyListViewItem * ki = new PropertyListViewItem(m_PropertiesListview); + ki->setMultiLinesEnabled(true); + ki->setText(0,dlg.propName()); + ki->setText(1,dlg.propValue()); + ki->checkName(); + ki->checkValue(); + } +} + +/*! + \fn PropertiesDlg::slotDelete + */ +void PropertiesDlg::slotDelete() +{ + QListViewItem*qi = m_PropertiesListview->selectedItem(); + if (!qi) return; + PropertyListViewItem*ki = static_cast<PropertyListViewItem*> (qi); + if (PropertyListViewItem::protected_Property(ki->currentName())) return; + if (ki->deleted()) { + ki->unDeleteIt(); + } else { + ki->deleteIt(); + } + slotSelectionChanged(qi); +} + + +/*! + \fn PropertiesDlg::slotModify() + */ +void PropertiesDlg::slotModify() +{ + QListViewItem*qi = m_PropertiesListview->selectedItem(); + if (!qi) return; + PropertyListViewItem*ki = static_cast<PropertyListViewItem*> (qi); + if (PropertyListViewItem::protected_Property(ki->currentName())) return; + /// @TODO Use a object variable to store a reference to dlg for further reuse + EditProperty_impl dlg(this); + dlg.setDir(m_Item->isDir()); + dlg.setPropName(ki->currentName()); + dlg.setPropValue(ki->currentValue()); + if (dlg.exec()==QDialog::Accepted) { + if (PropertyListViewItem::protected_Property(dlg.propName())) { + KMessageBox::error(this,i18n("This property may not set by users.\nRejecting it."),i18n("Protected property")); + return; + } + if (m_PropertiesListview->checkExisting(dlg.propName(),qi)) { + KMessageBox::error(this,i18n("A property with that name exists.\nRejecting it."),i18n("Double property")); + return; + } + ki->setText(0,dlg.propName()); + ki->setText(1,dlg.propValue()); + ki->checkName(); + ki->checkValue(); + } +} + +void PropertiesDlg::changedItems(svn::PropertiesMap&toSet,QValueList<QString>&toDelete) +{ + toSet.clear(); + toDelete.clear(); + QListViewItemIterator iter( m_PropertiesListview ); + PropertyListViewItem*ki; + while ( iter.current() ) { + ki = static_cast<PropertyListViewItem*> (iter.current()); + ++iter; + if (PropertyListViewItem::protected_Property(ki->currentName())|| + PropertyListViewItem::protected_Property(ki->startName())) { + continue; + } + if (ki->deleted()) { + toDelete.push_back(ki->currentName()); + } else if (ki->currentName()!=ki->startName()){ + toDelete.push_back(ki->startName()); + toSet[ki->currentName()]=ki->currentValue(); + } else if (ki->currentValue()!=ki->startValue()) { + toSet[ki->currentName()]=ki->currentValue(); + } + } +} + +#include "propertiesdlg.moc" diff --git a/src/svnfrontend/propertiesdlg.h b/src/svnfrontend/propertiesdlg.h new file mode 100644 index 0000000..006ad0a --- /dev/null +++ b/src/svnfrontend/propertiesdlg.h @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef PROPERTIESDLG_H +#define PROPERTIESDLG_H + +#include <qvariant.h> +#include <kdialogbase.h> +#include <qvaluelist.h> +#include <qmap.h> +#include <qstring.h> + +#include "src/svnqt/svnqttypes.hpp" +#include "src/svnqt/revision.hpp" + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QLabel; +class Propertylist; +class QListViewItem; +class KPushButton; +class FileListViewItem; +class SvnItem; + +namespace svn { + class Client; +} + +class PropertiesDlg : public KDialogBase +{ + Q_OBJECT + +public: + PropertiesDlg(SvnItem*, svn::Client*, + const svn::Revision&aRev=svn::Revision(svn_opt_revision_working), + QWidget* parent = 0, const char* name = 0, bool modal = true); + ~PropertiesDlg(); + + bool hasChanged()const; + void changedItems(svn::PropertiesMap&toSet,QValueList<QString>&toDelete); + +protected: + Propertylist* m_PropertiesListview; + KPushButton* m_AddButton; + KPushButton* m_DeleteButton; + KPushButton* m_ModifyButton; + + QHBoxLayout* PropertiesDlgLayout; + QVBoxLayout* m_rightLayout; + QSpacerItem* m_rightSpacer; + + SvnItem *m_Item; + bool m_changed; + bool initDone; + svn::Client*m_Client; + svn::Revision m_Rev; + +protected slots: + virtual void languageChange(); + + virtual void slotHelp(); + virtual void slotSelectionChanged(QListViewItem*); + virtual void slotSelectionExecuted(QListViewItem*); + virtual void slotAdd(); + virtual void slotDelete(); + virtual void slotModify(); + +protected: + virtual void initItem(); + +public slots: + int exec(); + virtual void polish(); + +signals: + void clientException(const QString&); +}; + +#endif // PROPERTIESDLG_H diff --git a/src/svnfrontend/simple_logcb.h b/src/svnfrontend/simple_logcb.h new file mode 100644 index 0000000..71f6d1d --- /dev/null +++ b/src/svnfrontend/simple_logcb.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SIMPLE_LOGCB_H +#define SIMPLE_LOGCB_H + +namespace svn +{ + class LogEntry; + class Revision; +} + +class QString; + +//! Helper for getting specific svn logentries +class SimpleLogCb +{ +public: + //! empty constructor + SimpleLogCb(){} + //! destructor + virtual ~SimpleLogCb(){} + //! retrieve a logentry + /*! + * @param logtarget target buffer where to store logentry + * @param rev Revision to get logentry + * @param what item to search for + * @param peg Peg revision, may equal to \a rev + * @param root the root repository of item, if not given, it has to get detected in implementation from \a what and used. + * @return true if logentry and root found, otherwise false. + */ + virtual bool getSingleLog(svn::LogEntry&logtarget,const svn::Revision&rev,const QString&what,const svn::Revision&peg,QString&root) = 0; +}; + +#endif diff --git a/src/svnfrontend/stopdlg.cpp b/src/svnfrontend/stopdlg.cpp new file mode 100644 index 0000000..06bee04 --- /dev/null +++ b/src/svnfrontend/stopdlg.cpp @@ -0,0 +1,216 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "stopdlg.h" +#include "ccontextlistener.h" +#include "settings/kdesvnsettings.h" +#include "helpers/stringhelper.h" + +#include <kapplication.h> +#include <klocale.h> +#include <kwin.h> +#include <qtimer.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qwidgetlist.h> +#include <kprogress.h> +#include <kdebug.h> +#include <ktextbrowser.h> + +StopDlg::StopDlg(QObject*listener,QWidget *parent, const char *name,const QString&caption,const QString&text) + : KDialogBase(KDialogBase::Plain,caption,KDialogBase::Cancel, KDialogBase::Cancel,parent, name,true) + ,m_Context(listener),m_MinDuration(1000),mCancelled(false),mShown(false),m_BarShown(false), + cstack(0) +{ + KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon()); + m_lastLogLines = 0; + m_lastLog = ""; + + mShowTimer = new QTimer(this); + m_StopTick.start(); + showButton(KDialogBase::Close, false); + mCancelText = actionButton(KDialogBase::Cancel)->text(); + + QFrame* mainWidget = plainPage(); + layout = new QVBoxLayout(mainWidget, 10); + mLabel = new QLabel(text, mainWidget); + layout->addWidget(mLabel); + m_ProgressBar=new KProgress(15,mainWidget); + m_ProgressBar->setCenterIndicator (false); + m_ProgressBar->setTextEnabled(false); + layout->addWidget(m_ProgressBar); + m_NetBar = new KProgress(15,mainWidget); + layout->addWidget(m_NetBar); + + mWait = false; + m_LogWindow = 0; + + connect(mShowTimer, SIGNAL(timeout()), this, SLOT(slotAutoShow())); + if (m_Context) { + connect(m_Context,SIGNAL(tickProgress()),this,SLOT(slotTick())); + connect(m_Context,SIGNAL(waitShow(bool)),this,SLOT(slotWait(bool))); + connect(m_Context,SIGNAL(netProgress(long long int, long long int)), + this,SLOT(slotNetProgres(long long int, long long int))); + connect(this,SIGNAL(sigCancel(bool)),m_Context,SLOT(setCanceled(bool))); + } + mShowTimer->start(m_MinDuration, true); + setMinimumSize(280,160); + adjustSize(); +} + +void StopDlg::showEvent( QShowEvent*) +{ + cstack = new CursorStack(Qt::BusyCursor); +} + +void StopDlg::hideEvent(QHideEvent*) +{ + delete cstack; cstack = 0; +} + +void StopDlg::slotWait(bool how) +{ + mWait = how; + if (mShown && mWait) { + hide(); + mShown = false; + } +} + +StopDlg::~StopDlg() +{ + delete cstack; +} + +void StopDlg::slotAutoShow() +{ + bool hasDialogs = false; + QWidget * w = kapp->activeModalWidget(); + if (w && w!=this && w!=parentWidget() ) { + hasDialogs = true; + } + if (hasDialogs) { + kdDebug()<<"Hide me! (" << caption() << ")" << endl; + hide(); + } + if (mShown||mWait||hasDialogs) { + if (mWait) { + //kdDebug() << "Waiting for show"<<endl; + mShowTimer->start(m_MinDuration, true); + } + mShowTimer->start(m_MinDuration, true); + return; + } + m_ProgressBar->hide(); + m_NetBar->hide(); + m_BarShown=false; + m_netBarShown=false; + show(); + kapp->processEvents(); + mShown = true; + mShowTimer->start(m_MinDuration, true); +} + +void StopDlg::slotCancel() +{ + mCancelled = true; + emit sigCancel(true); +} + +bool StopDlg::cancelld() +{ + return mCancelled; +} + +void StopDlg::slotTick() +{ + if (m_StopTick.elapsed()>500) { + if (!m_BarShown) { + m_ProgressBar->show(); + m_BarShown=true; + } + if (m_ProgressBar->progress()==15) { + m_ProgressBar->reset(); + } else { + m_ProgressBar->setProgress(m_ProgressBar->progress()+1); + } + m_StopTick.restart(); + kapp->processEvents(); + } +} + +void StopDlg::slotExtraMessage(const QString&msg) +{ + ++m_lastLogLines; + if (!m_LogWindow) { + QFrame* mainWidget = plainPage(); + m_LogWindow = new KTextBrowser(mainWidget); + layout->addWidget(m_LogWindow); + m_LogWindow->show(); + resize( QSize(500, 400).expandedTo(minimumSizeHint()) ); + } + if (m_lastLogLines >= Kdesvnsettings::self()->cmdline_log_minline() && + isHidden() ) { + slotAutoShow(); + } + m_LogWindow->append(msg); + kapp->processEvents(); +} + +void StopDlg::slotNetProgres(long long int current, long long int max) +{ + if (m_StopTick.elapsed()>300||(m_BarShown&&!m_netBarShown)) { + if (!m_netBarShown) { + m_NetBar->show(); + m_netBarShown=true; + } + QString s1 = helpers::ByteToString()(current); + if (max > -1 && max != m_NetBar->totalSteps()) { + QString s2 = helpers::ByteToString()(max); + m_NetBar->setFormat(i18n("%1 of %2").arg(s1).arg(s2)); + m_NetBar->setTotalSteps(max); + } + if (max == -1) { + m_NetBar->setFormat(i18n("%1 transferred.").arg(s1)); + m_NetBar->setTotalSteps(current+1); + } + m_NetBar->setValue(current); + m_StopTick.restart(); + kapp->processEvents(); + } +} + +StopSimpleDlg::StopSimpleDlg(QWidget *parent, const char *name,const QString&caption,const QString&text) + : StopDlg(0,parent,name,caption,text),cancelld(false) +{ + connect(this,SIGNAL(sigCancel(bool)),this,SLOT(slotSimpleCancel(bool))); +} + +void StopSimpleDlg::slotSimpleCancel(bool how) +{ + cancelld = how; +} + +void StopSimpleDlg::makeCancel() +{ + slotSimpleCancel(true); +} + +#include "stopdlg.moc" diff --git a/src/svnfrontend/stopdlg.h b/src/svnfrontend/stopdlg.h new file mode 100644 index 0000000..5d33d59 --- /dev/null +++ b/src/svnfrontend/stopdlg.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef STOPDLG_H +#define STOPDLG_H + +#include "src/svnfrontend/fronthelpers/cursorstack.h" + +#include <kdialogbase.h> + +#include <qdatetime.h> +#include <qobject.h> + +class QTimer; + +class CContextListener; +class QLabel; +class KProgress; +class KTextBrowser; +class QVBoxLayout; + +/** +@author Rajko Albrecht +*/ +class StopDlg : public KDialogBase +{ +Q_OBJECT +public: + StopDlg(QObject*,QWidget *parent = 0, const char *name = 0,const QString&caption=QString::null,const QString&text=QString::null); + virtual ~StopDlg(); + + bool cancelld(); + +protected: + QObject*m_Context; + int m_MinDuration; + bool mCancelled; + QTimer * mShowTimer; + QString mCancelText; + bool mShown,mWait; + QLabel*mLabel; + KProgress*m_ProgressBar; + KProgress*m_NetBar; + bool m_BarShown; + bool m_netBarShown; + QTime m_StopTick; + KTextBrowser*m_LogWindow; + QVBoxLayout*layout; + + QString m_lastLog; + unsigned int m_lastLogLines; + CursorStack * cstack; + + virtual void showEvent(QShowEvent*); + virtual void hideEvent(QHideEvent*); + +public slots: + virtual void slotTick(); + virtual void slotWait(bool); + virtual void slotExtraMessage(const QString&); + +protected slots: + virtual void slotAutoShow(); + virtual void slotCancel(); + virtual void slotNetProgres(long long int, long long int); +signals: + void sigCancel(bool how); +}; + +class StopSimpleDlg:public StopDlg +{ + Q_OBJECT +public: + StopSimpleDlg(QWidget *parent = 0, const char *name = 0,const QString&caption=QString::null,const QString&text=QString::null); + virtual ~StopSimpleDlg(){} + + bool isCanceld()const{return cancelld;} + +public slots: + virtual void makeCancel(); + +protected slots: + virtual void slotSimpleCancel(bool); + +protected: + bool cancelld; +}; + +#endif diff --git a/src/svnfrontend/svnactions.cpp b/src/svnfrontend/svnactions.cpp new file mode 100644 index 0000000..082666f --- /dev/null +++ b/src/svnfrontend/svnactions.cpp @@ -0,0 +1,2891 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnactions.h" +#include "checkoutinfo_impl.h" +#include "itemdisplay.h" +#include "svnitem.h" +#include "rangeinput_impl.h" +#include "propertiesdlg.h" +#include "ccontextlistener.h" +#include "tcontextlistener.h" +#include "modifiedthread.h" +#include "fillcachethread.h" +#include "svnlogdlgimp.h" +#include "stopdlg.h" +#include "blamedisplay_impl.h" +#include "src/ksvnwidgets/logmsg_impl.h" +#include "src/ksvnwidgets/diffbrowser.h" +#include "src/ksvnwidgets/encodingselector_impl.h" +#include "src/ksvnwidgets/revertform_impl.h" +#include "graphtree/revisiontree.h" +#include "src/settings/kdesvnsettings.h" +#include "src/kdesvn_events.h" +#include "src/svnqt/client.hpp" +#include "src/svnqt/annotate_line.hpp" +#include "src/svnqt/context_listener.hpp" +#include "src/svnqt/dirent.hpp" +#include "src/svnqt/targets.hpp" +#include "src/svnqt/url.hpp" +#include "src/svnqt/wc.hpp" +#include "src/svnqt/svnqt_defines.hpp" +#include "src/svnqt/cache/LogCache.hpp" +#include "src/svnqt/cache/ReposLog.hpp" +#include "src/svnqt/url.hpp" + +#include "helpers/sub2qt.h" +#include "fronthelpers/cursorstack.h" +#include "cacheentry.h" + +#include <kdialog.h> +#include <ktextbrowser.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kmessagebox.h> +#include <kinputdialog.h> +#include <kprocess.h> +#include <ktempdir.h> +#include <ktempfile.h> +#include <kdialogbase.h> +#include <kapplication.h> +#include <kio/jobclasses.h> +#include <kio/job.h> +#include <kdebug.h> +#include <kconfig.h> +#include <klistview.h> +#include <kio/netaccess.h> +#include <kstandarddirs.h> +#include <ktrader.h> +#include <krun.h> +#include <kstdguiitem.h> + +#include <qstring.h> +#include <qmap.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qvaluelist.h> +#include <qvbox.h> +#include <qstylesheet.h> +#include <qregexp.h> +#include <qimage.h> +#include <qthread.h> +#include <qtimer.h> +#include <qlistview.h> +#include <qfileinfo.h> +#include <sys/time.h> +#include <unistd.h> +#include <qguardedptr.h> + +// wait not longer than 10 seconds for a thread +#define MAX_THREAD_WAITTIME 10000 + +class SvnActionsData:public svn::ref_count +{ + typedef svn::SharedPointer<svn::PathPropertiesMapList> sPPlist; +public: + SvnActionsData():ref_count() + { + m_Svnclient = svn::Client::getobject(0,0); + m_CurrentContext = 0; + } + + virtual ~SvnActionsData() + { + if (m_DiffDialog) { + m_DiffDialog->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false); + delete m_DiffDialog; + } + if (m_LogDialog) { + m_LogDialog->saveSize(); + delete m_LogDialog; + } + + QMap<KProcess*,QStringList>::iterator it; + for (it=m_tempfilelist.begin();it!=m_tempfilelist.end();++it) { + for (QStringList::iterator it2 = (*it).begin(); + it2 != (*it).end();++it2) { + ::unlink((*it2).ascii()); + } + } + for (it=m_tempdirlist.begin();it!=m_tempdirlist.end();++it) { + for (QStringList::iterator it2 = (*it).begin(); + it2 != (*it).end();++it2) { + KIO::NetAccess::del((*it2),0); + } + } + delete m_Svnclient; + m_Svnclient = 0L; + } + + bool isExternalDiff() + { + if (Kdesvnsettings::use_external_diff()) { + QString edisp = Kdesvnsettings::external_diff_display(); + QStringList wlist = QStringList::split(" ",edisp); + if (wlist.count()>=3 && edisp.find("%1")!=-1 && edisp.find("%2")!=-1) { + return true; + } + } + return false; + } + + void clearCaches() + { + m_PropertiesCache.clear(); + m_contextData.clear(); + m_InfoCache.clear(); + } + + void cleanDialogs() + { + if (m_DiffDialog) { + m_DiffDialog->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false); + delete m_DiffDialog; + m_DiffDialog=0; + } + if (m_LogDialog) { + m_LogDialog->saveSize(); + delete m_LogDialog; + m_LogDialog=0; + } + } + + ItemDisplay* m_ParentList; + + svn::smart_pointer<CContextListener> m_SvnContextListener; + svn::ContextP m_CurrentContext; + svn::Client*m_Svnclient; + + helpers::statusCache m_UpdateCache; + helpers::statusCache m_Cache; + helpers::statusCache m_conflictCache; + helpers::statusCache m_repoLockCache; + helpers::itemCache<svn::PathPropertiesMapListPtr> m_PropertiesCache; + /// \todo as persistent cache (sqlite?) + helpers::itemCache<svn::InfoEntry> m_InfoCache; + + QMap<KProcess*,QStringList> m_tempfilelist; + QMap<KProcess*,QStringList> m_tempdirlist; + + QTimer m_ThreadCheckTimer; + QTimer m_UpdateCheckTimer; + QTime m_UpdateCheckTick; + QGuardedPtr<DiffBrowser> m_DiffBrowserPtr; + QGuardedPtr<KDialogBase> m_DiffDialog; + QGuardedPtr<SvnLogDlgImp> m_LogDialog; + + QMap<QString,QString> m_contextData; + + bool runblocked; +}; + +#define EMIT_FINISHED emit sendNotify(i18n("Finished")) +#define EMIT_REFRESH emit sigRefreshAll() +#define DIALOGS_SIZES "display_dialogs_sizes" + +SvnActions::SvnActions(ItemDisplay *parent, const char *name,bool processes_blocked) + : QObject(parent?parent->realWidget():0, name),SimpleLogCb() +{ + m_CThread = 0; + m_UThread = 0; + m_FCThread = 0; + m_Data = new SvnActionsData(); + m_Data->m_ParentList = parent; + m_Data->m_SvnContextListener = new CContextListener(this); + m_Data->runblocked = processes_blocked; + connect(m_Data->m_SvnContextListener,SIGNAL(sendNotify(const QString&)),this,SLOT(slotNotifyMessage(const QString&))); + connect(&(m_Data->m_ThreadCheckTimer),SIGNAL(timeout()),this,SLOT(checkModthread())); + connect(&(m_Data->m_UpdateCheckTimer),SIGNAL(timeout()),this,SLOT(checkUpdateThread())); +} + +svn::Client* SvnActions::svnclient() +{ + return m_Data->m_Svnclient; +} + +SvnActions::~SvnActions() +{ + killallThreads(); +} + +void SvnActions::slotNotifyMessage(const QString&aMsg) +{ + emit sendNotify(aMsg); +} + +void SvnActions::reInitClient() +{ + m_Data->clearCaches(); + m_Data->cleanDialogs(); + if (m_Data->m_CurrentContext) m_Data->m_CurrentContext->setListener(0L); + m_Data->m_CurrentContext = new svn::Context(); + m_Data->m_CurrentContext->setListener(m_Data->m_SvnContextListener); + m_Data->m_Svnclient->setContext(m_Data->m_CurrentContext); +} + +template<class T> KDialogBase* SvnActions::createDialog(T**ptr,const QString&_head,bool OkCancel,const char*name,bool showHelp,bool modal,const KGuiItem&u1) +{ + int buttons = KDialogBase::Ok; + if (OkCancel) { + buttons = buttons|KDialogBase::Cancel; + } + if (showHelp) { + buttons = buttons|KDialogBase::Help; + } + if (!u1.text().isEmpty()) { + buttons = buttons|KDialogBase::User1; + } + KDialogBase * dlg = new KDialogBase( + modal?KApplication::activeModalWidget():0, // parent + name, // name + modal, // modal + _head, // caption + buttons, // buttonmask + KDialogBase::Ok, // defaultButton + false , // separator + (u1.text().isEmpty()?KGuiItem():u1) //user1 + ); + + if (!dlg) return dlg; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + *ptr = new T(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),name?name:DIALOGS_SIZES)); + return dlg; +} + +/*! + \fn SvnActions::makeLog(svn::Revision start,svn::Revision end,FileListViewItem*k) + */ +void SvnActions::makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,SvnItem*k,bool list_files,int limit) +{ + if (k) { + makeLog(start,end,peg,k->fullName(),list_files,limit); + } +} + +svn::SharedPointer<svn::LogEntriesMap> SvnActions::getLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,const QString&which,bool list_files, + int limit,QWidget*parent) +{ + svn::SharedPointer<svn::LogEntriesMap> logs = new svn::LogEntriesMap; + if (!m_Data->m_CurrentContext) return 0; + + bool follow = Kdesvnsettings::log_follows_nodes(); + + kdDebug()<<"Get logs for "<< which<<endl; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,(parent?parent:m_Data->m_ParentList->realWidget()),0,"Logs", + i18n("Getting logs - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + if (doNetworking()) { + m_Data->m_Svnclient->log(which,start,end,*logs,peg,list_files,!follow,limit); + } else { + svn::InfoEntry e; + if (!singleInfo(m_Data->m_ParentList->baseUri(),svn::Revision::BASE,e)) { + return 0; + } + if (svn::Url::isLocal(e.reposRoot())) { + m_Data->m_Svnclient->log(which,start,end,*logs,peg,list_files,!follow,limit); + } else { + svn::cache::ReposLog rl(m_Data->m_Svnclient,e.reposRoot()); + QString s1,s2,what; + s1=e.url().mid(e.reposRoot().length()); + if (which==".") { + what=s1; + } else { + s2=which.mid(m_Data->m_ParentList->baseUri().length()); + what=s1+"/"+s2; + } + rl.log(what,start,end,peg,*logs,!follow,limit); + } + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return 0; + } + if (!logs) { + emit clientException(i18n("Got no logs")); + return 0; + } + return logs; +} + +bool SvnActions::getSingleLog(svn::LogEntry&t,const svn::Revision&r,const QString&what,const svn::Revision&peg,QString&root) +{ + bool res = false; + + if (what.isEmpty()) { + return res; + } + if (root.isEmpty()) { + svn::InfoEntry inf; + if (!singleInfo(what,peg,inf)) + { + return res; + } + root = inf.reposRoot(); + } + + if (!svn::Url::isLocal(root)) { + svn::LogEntriesMap _m; + try { + svn::cache::ReposLog rl(m_Data->m_Svnclient ,root); + if (rl.isValid() && rl.simpleLog(_m,r,r,true) && _m.find(r.revnum())!=_m.end() ) { + t = _m[r.revnum()]; + res = true; + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + } + } + + if (!res) { + svn::SharedPointer<svn::LogEntriesMap> log = getLog(r,r,peg,root,true,1); + if (log) { + if (log->find(r.revnum())!=log->end()) { + t = (*log)[r.revnum()]; + res = true; + } + } + } + return res; +} + +bool SvnActions::singleInfo(const QString&what,const svn::Revision&_rev,svn::InfoEntry&target,const svn::Revision&_peg) +{ + QString url; + QString ex; + QString cacheKey; + QTime d; d.start(); + svn::Revision rev = _rev; + svn::Revision peg = _peg; + if (!m_Data->m_CurrentContext) return false; + if (!svn::Url::isValid(what)) { + // working copy + // url = svn::Wc::getUrl(what); + url = what; + if (url.find("@")!=-1) { + url+="@BASE"; + } + peg = svn::Revision::UNDEFINED; + cacheKey=url; + } else { + KURL _uri = what; + QString prot = svn::Url::transformProtokoll(_uri.protocol()); + _uri.setProtocol(prot); + url = _uri.prettyURL(); + if (peg==svn::Revision::UNDEFINED) + { + peg = _rev; + } + if (peg==svn::Revision::UNDEFINED) + { + peg=svn::Revision::HEAD; + } + cacheKey=_rev.toString()+"/"+url; + } + svn::InfoEntries e; + + if (cacheKey.isEmpty() || !m_Data->m_InfoCache.findSingleValid(cacheKey,target)) { + try { + e = (m_Data->m_Svnclient->info(url,svn::DepthEmpty,_rev,peg)); + } catch (const svn::Exception&ce) { + kdDebug()<<"Singleinfo: "<<_rev.toString()<<endl; + kdDebug()<<"Singleinfo: "<<ce.msg() << endl; + emit clientException(ce.msg()); + return false; + } + if (e.count()<1||e[0].reposRoot().isEmpty()) { + emit clientException(i18n("Got no info.")); + return false; + } + target = e[0]; + if (!cacheKey.isEmpty()) { + m_Data->m_InfoCache.insertKey(e[0],cacheKey); + if (peg != svn::Revision::UNDEFINED && peg.kind()!= svn::Revision::NUMBER && peg.kind()!= svn::Revision::DATE ) { + // for persistent storage, store head into persistent cache makes no sense. + cacheKey=e[0].revision().toString()+"/"+url; + kdDebug()<<"Extra: "<<cacheKey<<endl; + m_Data->m_InfoCache.insertKey(e[0],cacheKey); + } + } + } + return true; +} + +void SvnActions::makeTree(const QString&what,const svn::Revision&_rev,const svn::Revision&startr,const svn::Revision&endr) +{ + svn::InfoEntry info; + if (!singleInfo(what,_rev,info)) { + return; + } + QString reposRoot = info.reposRoot(); + + bool restartCache = (m_FCThread && m_FCThread->running()); + if (restartCache) { + stopFillCache(); + } + kdDebug()<<"Logs for "<<reposRoot<<endl; + QWidget*disp; + KDialogBase dlg(m_Data->m_ParentList->realWidget(),"historylist",true,i18n("History of %1").arg(info.url().mid(reposRoot.length())), + KDialogBase::Ok, + KDialogBase::Ok,true); + QWidget* Dialog1Layout = dlg.makeVBoxMainWidget(); + + RevisionTree rt(m_Data->m_Svnclient,m_Data->m_SvnContextListener,reposRoot, + startr,endr, + info.prettyUrl().mid(reposRoot.length()),_rev,Dialog1Layout,m_Data->m_ParentList->realWidget()); + if (rt.isValid()) { + disp = rt.getView(); + if (disp) { + connect( + disp,SIGNAL(makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + this,SLOT(makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)) + ); + connect( + disp,SIGNAL(makeRecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + this,SLOT(makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)) + ); + connect(disp,SIGNAL(makeCat(const svn::Revision&, const QString&,const QString&,const svn::Revision&,QWidget*)), + this,SLOT(slotMakeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*))); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),"revisiontree_dlg")); + dlg.exec(); + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"revisiontree_dlg",false); + } + } + if (restartCache) { + startFillCache(reposRoot); + } +} + +void SvnActions::makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,const QString&which,bool list_files,int limit) +{ + svn::InfoEntry info; + if (!singleInfo(which,start,info)) { + return; + } + QString reposRoot = info.reposRoot(); + kdDebug()<<"getting logs..."<<endl; + svn::SharedPointer<svn::LogEntriesMap> logs = getLog(start,end,peg,which,list_files,limit); + if (!logs) return; + bool need_modal = m_Data->runblocked||KApplication::activeModalWidget()!=0; + if (need_modal||!m_Data->m_LogDialog) { + m_Data->m_LogDialog=new SvnLogDlgImp(this,0,"logdialog",need_modal); + connect(m_Data->m_LogDialog,SIGNAL(makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*)), + this,SLOT(makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*))); + connect(m_Data->m_LogDialog,SIGNAL(makeCat(const svn::Revision&, const QString&,const QString&,const svn::Revision&,QWidget*)), + this,SLOT(slotMakeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*))); + } + + if (m_Data->m_LogDialog) { + m_Data->m_LogDialog->dispLog(logs,info.url().mid(reposRoot.length()),reposRoot, + ( + peg==svn::Revision::UNDEFINED? + (svn::Url::isValid(which)?svn::Revision::HEAD:svn::Revision::UNDEFINED): + peg + ),which); + if (need_modal) { + m_Data->m_LogDialog->exec(); + m_Data->m_LogDialog->saveSize(); + delete m_Data->m_LogDialog; + } else { + m_Data->m_LogDialog->show(); + m_Data->m_LogDialog->raise(); + } + } + EMIT_FINISHED; +} + +void SvnActions::makeBlame(const svn::Revision&start, const svn::Revision&end, SvnItem*k) +{ + if (k) makeBlame(start,end,k->fullName(),m_Data->m_ParentList->realWidget()); +} + +void SvnActions::makeBlame(const svn::Revision&start, const svn::Revision&end,const QString&k,QWidget*_p,const svn::Revision&_peg,SimpleLogCb*_acb) +{ + if (!m_Data->m_CurrentContext) return; + svn::AnnotatedFile blame; + QString ex; + svn::Path p(k); + QWidget*_parent = _p?_p:m_Data->m_ParentList->realWidget(); + svn::Revision peg = _peg==svn::Revision::UNDEFINED?end:_peg; + + try { + CursorStack a(Qt::BusyCursor); + StopDlg sdlg(m_Data->m_SvnContextListener,_parent,0,"Annotate",i18n("Annotate lines - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->annotate(blame,p,start,end,peg); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + if (blame.count()==0) { + ex = i18n("Got no annotate"); + emit clientException(ex); + return; + } + EMIT_FINISHED; + BlameDisplay_impl::displayBlame(_acb?_acb:this,k,blame,_p,"blame_dlg"); +} + +bool SvnActions::makeGet(const svn::Revision&start, const QString&what, const QString&target, + const svn::Revision&peg,QWidget*_dlgparent) +{ + if (!m_Data->m_CurrentContext) return false; + CursorStack a(Qt::BusyCursor); + QWidget*dlgp=_dlgparent?_dlgparent:m_Data->m_ParentList->realWidget(); + QString ex; + svn::Path p(what); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,dlgp, + 0,"Content get",i18n("Getting content - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->get(p,target,start,peg); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } catch (...) { + ex = i18n("Error getting content"); + emit clientException(ex); + return false; + } + return true; +} + +void SvnActions::slotMakeCat(const svn::Revision&start, const QString&what, const QString&disp,const svn::Revision&peg,QWidget*_dlgparent) +{ + KTempFile content; + content.setAutoDelete(true); + if (!makeGet(start,what,content.name(),peg,_dlgparent)) { + return; + } + EMIT_FINISHED; + KMimeType::Ptr mptr; + mptr = KMimeType::findByFileContent(content.name()); + KTrader::OfferList offers = KTrader::self()->query(mptr->name(), "Type == 'Application' or (exist Exec)"); + if (offers.count()==0 || offers.first()->exec().isEmpty()) { + offers = KTrader::self()->query(mptr->name(), "Type == 'Application'"); + } + KTrader::OfferList::ConstIterator it = offers.begin(); + for( ; it != offers.end(); ++it ) { + if ((*it)->noDisplay()) + continue; + break; + } + + if (it!=offers.end()) { + content.setAutoDelete(false); + KRun::run(**it,KURL(content.name()),true); + return; + } + KTextBrowser*ptr; + QFile file(content.name()); + file.open( IO_ReadOnly ); + QByteArray co = file.readAll(); + + if (co.size()) { + KDialogBase*dlg = createDialog(&ptr,QString(i18n("Content of %1")).arg(disp),false,"cat_display_dlg"); + if (dlg) { + ptr->setFont(KGlobalSettings::fixedFont()); + ptr->setWordWrap(QTextEdit::NoWrap); + ptr->setText(QString::FROMUTF8(co,co.size())); + dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"cat_display_dlg",false); + delete dlg; + } + } else { + KMessageBox::information(_dlgparent?_dlgparent:m_Data->m_ParentList->realWidget(), + i18n("Got no content.")); + } +} + +bool SvnActions::makeMkdir(const QStringList&which,const QString&logMessage) +{ + if (!m_Data->m_CurrentContext||which.count()<1) return false; + svn::Targets targets(which); + try { + m_Data->m_Svnclient->mkdir(targets,logMessage); + }catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +QString SvnActions::makeMkdir(const QString&parentDir) +{ + if (!m_Data->m_CurrentContext) return QString::null; + QString ex; + bool isOk=false; + ex = KInputDialog::getText(i18n("New folder"),i18n("Enter folder name:"),QString::null,&isOk); + if (!isOk) { + return QString::null; + } + svn::Path target(parentDir); + target.addComponent(ex); + ex = ""; + + QString logMessage=QString::null; + try { + m_Data->m_Svnclient->mkdir(target,logMessage); + }catch (const svn::Exception&e) { + emit clientException(e.msg()); + return QString::null; + } + + ex = target.path(); + return ex; +} + +QString SvnActions::getInfo(QPtrList<SvnItem> lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all) +{ + QStringList l; + QString res = ""; + SvnItem*item; + for (item=lst.first();item;item=lst.next()) { + if (all) res+="<h4 align=\"center\">"+item->fullName()+"</h4>"; + res += getInfo(item->fullName(),rev,peg,recursive,all); + } + return res; +} + +QString SvnActions::getInfo(const QString& _what,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all) +{ + if (!m_Data->m_CurrentContext) return QString::null; + QString ex; + svn::InfoEntries entries; + if (recursive) { + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Details", + i18n("Retrieving infos - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + svn::InfoEntries e; + entries = (m_Data->m_Svnclient->info(_what+ + (_what.find("@")>-1&&!svn::Url::isValid(_what)?"@BASE":""),recursive?svn::DepthInfinity:svn::DepthEmpty,rev,peg)); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return QString::null; + } + } else { + svn::InfoEntry info; + if (!singleInfo(_what,rev,info,peg)) { + return QString::null; + } + entries.append(info); + } + //if (!all) EMIT_FINISHED; + QString text = ""; + svn::InfoEntries::const_iterator it; + static QString rb = "<tr><td><nobr><font color=\"black\">"; + static QString re = "</font></nobr></td></tr>\n"; + static QString cs = "</font></nobr>:</td><td><nobr><font color=\"black\">"; + unsigned int val = 0; + for (it=entries.begin();it!=entries.end();++it) { + if (val>0) { + text+="<hline>"; + } + text+="<p align=\"center\">"; + text+="<table cellspacing=0 cellpadding=0>"; + if ((*it).Name().length()) { + text+=rb+i18n("Name")+cs+((*it).Name())+re; + } + if (all) { + text+=rb+i18n("URL")+cs+((*it).url())+re; + if ((*it).reposRoot().length()) { + text+=rb+i18n("Canonical repository url")+cs+((*it).reposRoot())+re; + } + if ((*it).checksum().length()) { + text+=rb+i18n("Checksum")+cs+((*it).checksum())+re; + } + } + text+=rb+i18n("Type")+cs; + switch ((*it).kind()) { + case svn_node_none: + text+=i18n("Absent"); + break; + case svn_node_file: + text+=i18n("File"); + break; + case svn_node_dir: + text+=i18n("Folder"); + break; + case svn_node_unknown: + default: + text+=i18n("Unknown"); + break; + } + text+=re; + if (all) { + text+=rb+i18n("Schedule")+cs; + switch ((*it).Schedule()) { + case svn_wc_schedule_normal: + text+=i18n("Normal"); + break; + case svn_wc_schedule_add: + text+=i18n("Addition"); + break; + case svn_wc_schedule_delete: + text+=i18n("Deletion"); + break; + case svn_wc_schedule_replace: + text+=i18n("Replace"); + break; + default: + text+=i18n("Unknown"); + break; + } + text+=re; + text+=rb+i18n("UUID")+cs+((*it).uuid())+re; + } + text+=rb+i18n("Last author")+cs+((*it).cmtAuthor())+re; + if ((*it).cmtDate()>0) { + text+=rb+i18n("Last committed")+cs+helpers::sub2qt::DateTime2qtString((*it).cmtDate())+re; + } + text+=rb+i18n("Last revision")+cs+(*it).cmtRev().toString()+re; + if ((*it).textTime()>0) { + text+=rb+i18n("Content last changed")+cs+helpers::sub2qt::DateTime2qtString((*it).textTime())+re; + } + if (all) { + if ((*it).propTime()>0) { + text+=rb+i18n("Property last changed")+cs+helpers::sub2qt::DateTime2qtString((*it).propTime())+re; + } + if ((*it).conflictNew().length()) { + text+=rb+i18n("New version of conflicted file")+cs+((*it).conflictNew())+re; + } + if ((*it).conflictOld().length()) { + text+=rb+i18n("Old version of conflicted file")+cs+((*it).conflictOld())+re; + } + if ((*it).conflictWrk().length()) { + text+=rb+i18n("Working version of conflicted file")+ + cs+((*it).conflictWrk())+re; + } + if ((*it).prejfile().length()) { + text+=rb+i18n("Property reject file")+ + cs+((*it).prejfile())+re; + } + + if ((*it).copyfromUrl().length()) { + text+=rb+i18n("Copy from URL")+cs+((*it).copyfromUrl())+re; + } + if ((*it).lockEntry().Locked()) { + text+=rb+i18n("Lock token")+cs+((*it).lockEntry().Token())+re; + text+=rb+i18n("Owner")+cs+((*it).lockEntry().Owner())+re; + text+=rb+i18n("Locked on")+cs+ + helpers::sub2qt::DateTime2qtString((*it).lockEntry().Date())+ + re; + text+=rb+i18n("Lock comment")+cs+ + (*it).lockEntry().Comment()+re; + } else { + svn::SharedPointer<svn::Status> d; + if (checkReposLockCache(_what,d)&& d && d->lockEntry().Locked()) { + text+=rb+i18n("Lock token")+cs+(d->lockEntry().Token())+re; + text+=rb+i18n("Owner")+cs+(d->lockEntry().Owner())+re; + text+=rb+i18n("Locked on")+cs+ + helpers::sub2qt::DateTime2qtString(d->lockEntry().Date())+ + re; + text+=rb+i18n("Lock comment")+cs+ + d->lockEntry().Comment()+re; + } + } + } + text+="</table></p>\n"; + } + return text; +} + +void SvnActions::makeInfo(QPtrList<SvnItem> lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive) +{ + QStringList l; + QString res = "<html><head></head><body>"; + SvnItem*item; + for (item=lst.first();item;item=lst.next()) { + QString text = getInfo(item->fullName(),rev,peg,recursive,true); + if (!text.isEmpty()) { + res+="<h4 align=\"center\">"+item->fullName()+"</h4>"; + res+=text; + } + } + res+="</body></html>"; + KTextBrowser*ptr; + KDialogBase*dlg = createDialog(&ptr,QString(i18n("Infolist")),false,"info_dialog"); + if (dlg) { + ptr->setText(res); + dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"info_dialog",false); + delete dlg; + } +} + +void SvnActions::makeInfo(const QStringList&lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive) +{ + QString text = ""; + for (unsigned int i=0; i < lst.count();++i) { + QString res = getInfo(lst[i],rev,peg,recursive,true); + if (!res.isEmpty()) { + text+="<h4 align=\"center\">"+lst[i]+"</h4>"; + text+=res; + } + } + text = "<html><head></head><body>"+text+"</body></html>"; + KTextBrowser*ptr; + KDialogBase*dlg = createDialog(&ptr,QString(i18n("Infolist")),false,"info_dialog"); + if (dlg) { + ptr->setText(text); + dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"info_dialog",false); + delete dlg; + } +} + + +/*! + \fn SvnActions::slotProperties() + */ +void SvnActions::slotProperties() +{ + /// @todo remove reference to parentlist + if (!m_Data->m_CurrentContext) return; + if (!m_Data->m_ParentList) return; + SvnItem*k = m_Data->m_ParentList->Selected(); + if (!k) return; + PropertiesDlg dlg(k,svnclient(), + m_Data->m_ParentList->isWorkingCopy()?svn::Revision::WORKING:svn::Revision::HEAD); + connect(&dlg,SIGNAL(clientException(const QString&)),m_Data->m_ParentList->realWidget(),SLOT(slotClientException(const QString&))); + dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()), "properties_dlg")); + if (dlg.exec()!=QDialog::Accepted) { + return; + } + dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"properties_dlg",false); + QString ex; + svn::PropertiesMap setList; + QValueList<QString> delList; + dlg.changedItems(setList,delList); + changeProperties(setList,delList,k->fullName()); + k->refreshStatus(); + EMIT_FINISHED; +} + +bool SvnActions::changeProperties(const svn::PropertiesMap&setList,const QValueList<QString>&delList,const QString&path) +{ + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Applying properties","<center>Applying<br>hit cancel for abort</center>"); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + unsigned int pos; + for (pos = 0; pos<delList.size();++pos) { + m_Data->m_Svnclient->propdel(delList[pos],svn::Path(path)); + } + svn::PropertiesMap::ConstIterator it; + for (it=setList.begin(); it!=setList.end();++it) { + m_Data->m_Svnclient->propset(it.key(),it.data(),svn::Path(path)); + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +/*! + \fn SvnActions::slotCommit() + */ +void SvnActions::slotCommit() +{ + if (!m_Data->m_CurrentContext||!m_Data->m_ParentList->isWorkingCopy()) { + return; + } + QPtrList<SvnItem> which; + m_Data->m_ParentList->SelectionList(&which); + SvnItem*cur; + QPtrListIterator<SvnItem> liter(which); + + svn::Pathes targets; + if (which.count()==0) { + targets.push_back(svn::Path(".")); + } else { + while ( (cur=liter.current())!=0) { + ++liter; + targets.push_back(svn::Path( + m_Data->m_ParentList->relativePath(cur) + )); + } + } + if (m_Data->m_ParentList->baseUri().length()>0) { + chdir(m_Data->m_ParentList->baseUri().local8Bit()); + } + if (makeCommit(targets) && Kdesvnsettings::log_cache_on_open()) { + startFillCache(m_Data->m_ParentList->baseUri()); + } +} + +bool SvnActions::makeCommit(const svn::Targets&targets) +{ + bool ok,keeplocks; + svn::Depth depth; + svn::Revision nnum; + svn::Targets _targets; + svn::Pathes _deldir; + bool review = Kdesvnsettings::review_commit(); + QString msg,_p; + + if (!doNetworking()) { + emit clientException(i18n("Not commiting because networking is disabled")); + return false; + } + + stopFillCache(); + if (!review) { + msg = Logmsg_impl::getLogmessage(&ok,&depth,&keeplocks, + m_Data->m_ParentList->realWidget(),"logmsg_impl"); + if (!ok) { + return false; + } + _targets = targets; + } else { + Logmsg_impl::logActionEntries _check,_uncheck,_result; + svn::StatusEntries _Cache; + depth=svn::DepthEmpty; + /// @todo filter out double entries + for (unsigned j = 0; j < targets.size(); ++j) { + svn::Revision where = svn::Revision::HEAD; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Status / List"),i18n("Creating list / check status")); + _Cache = m_Data->m_Svnclient->status(targets.target(j).path(),svn::DepthInfinity,false,false,false,where); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + for (unsigned int i = 0; i < _Cache.count();++i) { + _p = _Cache[i]->path(); + if (_Cache[i]->isRealVersioned()&& ( + _Cache[i]->textStatus()==svn_wc_status_modified|| + _Cache[i]->textStatus()==svn_wc_status_added|| + _Cache[i]->textStatus()==svn_wc_status_replaced|| + _Cache[i]->textStatus()==svn_wc_status_deleted|| + _Cache[i]->propStatus()==svn_wc_status_modified + ) ) { + if (_Cache[i]->textStatus()==svn_wc_status_deleted) { + _check.append(Logmsg_impl::logActionEntry(_p,i18n("Delete"),Logmsg_impl::logActionEntry::DELETE)); + } else { + _check.append(Logmsg_impl::logActionEntry(_p,i18n("Commit"),Logmsg_impl::logActionEntry::COMMIT)); + } + } else if (_Cache[i]->textStatus()==svn_wc_status_missing) { + _uncheck.append(Logmsg_impl::logActionEntry(_p,i18n("Delete and Commit"),Logmsg_impl::logActionEntry::MISSING_DELETE)); + } else if (!_Cache[i]->isVersioned()) { + _uncheck.append(Logmsg_impl::logActionEntry(_p,i18n("Add and Commit"),Logmsg_impl::logActionEntry::ADD_COMMIT)); + } + } + } + msg = Logmsg_impl::getLogmessage(_check,_uncheck,this,_result,&ok,&keeplocks, + m_Data->m_ParentList->realWidget(),"logmsg_impl"); + if (!ok||_result.count()==0) { + return false; + } + svn::Pathes _add,_commit,_delete; + for (unsigned int i=0; i < _result.count();++i) { + if (_result[i]._kind==Logmsg_impl::logActionEntry::DELETE) { + QFileInfo fi(_result[i]._name); + if (fi.isDir()) { + depth = svn::DepthInfinity; + } + } + _commit.append(_result[i]._name); + if (_result[i]._kind==Logmsg_impl::logActionEntry::ADD_COMMIT) { + _add.append(_result[i]._name); + } else if (_result[i]._kind==Logmsg_impl::logActionEntry::MISSING_DELETE) { + _delete.append(_result[i]._name); + } + } + if (_add.count()>0) { + if (!addItems(_add,svn::DepthEmpty)) { + return false; + } + } + if (_delete.count()>0) { + makeDelete(_delete); + } + _targets = svn::Targets(_commit); + } + + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Commiting"), + i18n("Commiting - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + nnum = m_Data->m_Svnclient->commit(_targets,msg,depth,keeplocks); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + EMIT_REFRESH; + emit sendNotify(i18n("Committed revision %1.").arg(nnum.toString())); + return true; +} + +/*! + \fn SvnActions::wroteStdin(KProcess*) + */ +void SvnActions::wroteStdin(KProcess*proc) +{ + if (!proc) return; + kdDebug()<<"void SvnActions::wroteStdin(KProcess*proc)"<<endl; + proc->closeStdin(); +} + +void SvnActions::receivedStderr(KProcess*proc,char*buff,int len) +{ + if (!proc || !buff || len == 0) { + return; + } + QString msg(QCString(buff,len)); + emit sendNotify(msg); +} + +void SvnActions::procClosed(KProcess*proc) +{ + if (!proc) return; + QMap<KProcess*,QStringList>::iterator it; + if ( (it=m_Data->m_tempfilelist.find(proc))!=m_Data->m_tempfilelist.end()) { + for (QStringList::iterator it2 = (*it).begin(); + it2 != (*it).end();++it2) { + ::unlink((*it2).ascii()); + } + m_Data->m_tempfilelist.erase(it); + } + if ( (it=m_Data->m_tempdirlist.find(proc))!=m_Data->m_tempdirlist.end()) { + for (QStringList::iterator it2 = (*it).begin(); + it2 != (*it).end();++it2) { + KIO::NetAccess::del((*it2),0); + } + m_Data->m_tempdirlist.erase(it); + } + delete proc; +} + +bool SvnActions::get(const QString&what,const QString& to,const svn::Revision&rev,const svn::Revision&peg,QWidget*p) +{ + svn::Revision _peg = peg; + if (_peg == svn::Revision::UNDEFINED) { + _peg = rev; + } + + try { + StopDlg sdlg(m_Data->m_SvnContextListener,p?p:m_Data->m_ParentList->realWidget(),0,"Downloading", + i18n("Download - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->get(svn::Path(what), + to,rev,_peg); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +/*! + \fn SvnActions::makeDiff(const QString&,const svn::Revision&start,const svn::Revision&end) + */ +void SvnActions::makeDiff(const QString&what,const svn::Revision&start,const svn::Revision&end,const svn::Revision&_peg,bool isDir) +{ + makeDiff(what,start,what,end,_peg,isDir,m_Data->m_ParentList->realWidget()); +} + +void SvnActions::makeDiff(const QString&p1,const svn::Revision&start,const QString&p2,const svn::Revision&end) +{ + makeDiff(p1,start,p2,end,(QWidget*)0); +} + +void SvnActions::makeDiff(const QString&p1,const svn::Revision&start,const QString&p2,const svn::Revision&end,QWidget*p) +{ + if (!doNetworking()&&start!=svn::Revision::BASE && end!=svn::Revision::WORKING) { + emit sendNotify(i18n("Can not do this diff because networking is disabled.")); + kdDebug()<<"No diff 'cause no network"<<endl; + return; + } + if (m_Data->isExternalDiff()) { + kdDebug()<<"External diff..."<<endl; + svn::InfoEntry info; + if (singleInfo(p1,start,info)) { + makeDiff(p1,start,p2,end,end,info.isDir(),p); + } + return; + } + makeDiffinternal(p1,start,p2,end,p); +} + +void SvnActions::makeDiffExternal(const QString&p1,const svn::Revision&start,const QString&p2,const svn::Revision&end,const svn::Revision&_peg, + bool isDir,QWidget*p,bool rec) +{ + QString edisp = Kdesvnsettings::external_diff_display(); + QStringList wlist = QStringList::split(" ",edisp); + QFileInfo f1(p1); + QFileInfo f2(p2); + KTempFile tfile(QString::null,f1.fileName()+"-"+start.toString()),tfile2(QString::null,f2.fileName()+"-"+end.toString()); + QString s1 = f1.fileName()+"-"+start.toString(); + QString s2 = f2.fileName()+"-"+end.toString(); + KTempDir tdir1; + tdir1.setAutoDelete(true); + tfile.setAutoDelete(true); + tfile2.setAutoDelete(true); + QString first,second; + svn::Revision peg = _peg; + + if (start != svn::Revision::WORKING) { + first = isDir?tdir1.name()+"/"+s1:tfile.name(); + } else { + first = p1; + } + if (end!=svn::Revision::WORKING) { + second = isDir?tdir1.name()+"/"+s2:tfile2.name(); + } else { + second = p2; + } + if (second == first) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Both entries seems to be the same, can not diff.")); + return; + } + kdDebug()<<"Diff: "<<peg.toString()<<endl; + + if (start != svn::Revision::WORKING) { + if (!isDir) { + if (!get(p1,tfile.name(),start,peg,p)) { + return; + } + } else { + if (!makeCheckout(p1,first,start,peg, + rec?svn::DepthInfinity:svn::DepthFiles,true,false,false,false,p)) { + return; + } + } + } + if (end!=svn::Revision::WORKING) { + if (!isDir) { + if (!get(p2,tfile2.name(),end,peg,p)) { + return; + } + } else { + if (!makeCheckout(p2,second,end,peg, + rec?svn::DepthInfinity:svn::DepthFiles,true,false,false,false,p)) { + return; + } + } + } + KProcess*proc = new KProcess(); + for ( QStringList::Iterator it = wlist.begin();it!=wlist.end();++it) { + if (*it=="%1") { + *proc<<first; + } else if (*it=="%2") { + *proc<<second; + } else { + *proc << *it; + } + } + connect(proc,SIGNAL(processExited(KProcess*)),this,SLOT(procClosed(KProcess*))); + connect(proc,SIGNAL(receivedStderr(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + connect(proc,SIGNAL(receivedStdout(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + if (proc->start(m_Data->runblocked?KProcess::Block:KProcess::NotifyOnExit,KProcess::All)) { + if (!m_Data->runblocked) { + if (!isDir) { + tfile2.setAutoDelete(false); + tfile.setAutoDelete(false); + m_Data->m_tempfilelist[proc].append(tfile.name()); + m_Data->m_tempfilelist[proc].append(tfile2.name()); + } else { + tdir1.setAutoDelete(false); + m_Data->m_tempdirlist[proc].append(tdir1.name()); + } + } + return; + } else { + emit sendNotify(i18n("Diff-process could not started, check command.")); + } + delete proc; + return; +} + +void SvnActions::makeDiff(const QString&p1,const svn::Revision&start,const QString&p2,const svn::Revision&end,const svn::Revision&_peg,bool isDir,QWidget*p) +{ + if (m_Data->isExternalDiff()) { + kdDebug()<<"External diff 2..."<<endl; + makeDiffExternal(p1,start,p2,end,_peg,isDir,p); + } else { + makeDiffinternal(p1,start,p2,end,p,_peg); + } +} + +void SvnActions::makeDiffinternal(const QString&p1,const svn::Revision&r1,const QString&p2,const svn::Revision&r2,QWidget*p,const svn::Revision&_peg) +{ + if (!m_Data->m_CurrentContext) return; + QByteArray ex; + KTempDir tdir; + tdir.setAutoDelete(true); + QString tn = QString("%1/%2").arg(tdir.name()).arg("/svndiff"); + bool ignore_content = Kdesvnsettings::diff_ignore_content(); + QWidget*parent = p?p:m_Data->m_ParentList->realWidget(); + QStringList extraOptions; + if (Kdesvnsettings::diff_ignore_spaces()) + { + extraOptions.append("-b"); + } + if (Kdesvnsettings::diff_ignore_all_white_spaces()) + { + extraOptions.append("-w"); + } + svn::Revision peg = _peg==svn::Revision::UNDEFINED?r2:_peg; + + try { + StopDlg sdlg(m_Data->m_SvnContextListener,parent,0,"Diffing", + i18n("Diffing - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + if (p1==p2 && (r1.isRemote()||r2.isRemote())) { + kdDebug()<<"Pegged diff"<<endl; + ex = m_Data->m_Svnclient->diff_peg(svn::Path(tn), + svn::Path(p1),svn::Path(),r1, r2,peg, + svn::DepthInfinity,false,false,ignore_content,extraOptions,svn::StringArray()); + } else { + ex = m_Data->m_Svnclient->diff(svn::Path(tn), + svn::Path(p1),svn::Path(p2),svn::Path(), + r1, r2, + svn::DepthInfinity,false,false,ignore_content,extraOptions,svn::StringArray()); + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + EMIT_FINISHED; + if (ex.isEmpty()) { + emit clientException(i18n("No difference to display")); + return; + } + dispDiff(ex); +} + +void SvnActions::makeNorecDiff(const QString&p1,const svn::Revision&r1,const QString&p2,const svn::Revision&r2,QWidget*_p) +{ + if (!m_Data->m_CurrentContext) return; + if (m_Data->isExternalDiff()) { + svn::InfoEntry info; + if (singleInfo(p1,r1,info)) { + makeDiffExternal(p1,r1,p2,r2,r2,info.isDir(),_p,false); + } + return; + } + QStringList extraOptions; + if (Kdesvnsettings::diff_ignore_spaces()) + { + extraOptions.append("-b"); + } + if (Kdesvnsettings::diff_ignore_all_white_spaces()) + { + extraOptions.append("-w"); + } + QByteArray ex; + KTempDir tdir; + tdir.setAutoDelete(true); + kdDebug()<<"Non recourse diff"<<endl; + QString tn = QString("%1/%2").arg(tdir.name()).arg("/svndiff"); + bool ignore_content = Kdesvnsettings::diff_ignore_content(); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,_p?_p:m_Data->m_ParentList->realWidget(),0,"Diffing","Diffing - hit cancel for abort"); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + ex = m_Data->m_Svnclient->diff(svn::Path(tn), + svn::Path(p1),svn::Path(p2),svn::Path(), + r1, r2, + svn::DepthEmpty,false,false,ignore_content,extraOptions,svn::StringArray()); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + EMIT_FINISHED; + if (ex.isEmpty()) { + emit clientException(i18n("No difference to display")); + return; + } + + dispDiff(ex); +} + +void SvnActions::dispDiff(const QByteArray&ex) +{ + QString what = Kdesvnsettings::external_diff_display(); + int r = KProcess::Stdin|KProcess::Stderr; + + if (Kdesvnsettings::use_external_diff() && (what.find("%1")==-1 || what.find("%2")==-1)) { + QStringList wlist = QStringList::split(" ",what); + KProcess*proc = new KProcess(); + bool fname_used = false; + KTempFile tfile; + tfile.setAutoDelete(false); + + for ( QStringList::Iterator it = wlist.begin();it!=wlist.end();++it) { + if (*it=="%f") { + fname_used = true; + QDataStream*ds = tfile.dataStream(); + ds->writeRawBytes(ex,ex.size()); + tfile.close(); + *proc<<tfile.name(); + } else { + *proc << *it; + } + } + + connect(proc,SIGNAL(processExited(KProcess*)),this,SLOT(procClosed(KProcess*))); + connect(proc,SIGNAL(receivedStderr(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + if (!fname_used) { + connect(proc,SIGNAL(wroteStdin(KProcess*)),this,SLOT(wroteStdin(KProcess*))); + } + if (proc->start(KProcess::NotifyOnExit,fname_used?KProcess::Stderr:(KProcess::Communication)r)) { + if (!fname_used) proc->writeStdin(ex,ex.size()); + else m_Data->m_tempfilelist[proc].append(tfile.name()); + return; + } else { + emit sendNotify(i18n("Display-process could not started, check command.")); + } + delete proc; + } + bool need_modal = m_Data->runblocked||KApplication::activeModalWidget()!=0; + if (need_modal||!m_Data->m_DiffBrowserPtr||!m_Data->m_DiffDialog) { + DiffBrowser*ptr; + + if (!need_modal && m_Data->m_DiffBrowserPtr) { + delete m_Data->m_DiffBrowserPtr; + } + KDialogBase*dlg = createDialog(&ptr,QString(i18n("Diff display")),false, + "diff_display",false,need_modal, + KStdGuiItem::saveAs()); + if (dlg) { + QWidget*wd = dlg->mainWidget(); + if (wd) { + EncodingSelector_impl * ls = new EncodingSelector_impl("",wd); + QObject::connect(ls,SIGNAL(TextCodecChanged(const QString&)), + ptr,SLOT(slotTextCodecChanged(const QString&))); + } + QObject::connect(dlg,SIGNAL(user1Clicked()),ptr,SLOT(saveDiff())); + ptr->setText(ex); + if (need_modal) { + ptr->setFocus(); + dlg->exec(); + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false); + delete dlg; + return; + } else { + m_Data->m_DiffBrowserPtr=ptr; + m_Data->m_DiffDialog=dlg; + } + } + } else { + m_Data->m_DiffBrowserPtr->setText(ex); + m_Data->m_DiffBrowserPtr->setFocus(); + } + if (m_Data->m_DiffDialog) { + m_Data->m_DiffDialog->show(); + m_Data->m_DiffDialog->raise(); + } +} + + +/*! + \fn SvnActions::makeUpdate(const QString&what,const svn::Revision&rev,bool recurse) + */ +void SvnActions::makeUpdate(const QStringList&what,const svn::Revision&rev,bool recurse) +{ + if (!m_Data->m_CurrentContext) return; + QString ex; + svn::Revisions ret; + stopCheckUpdateThread(); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Making update", + i18n("Making update - hit cancel for abort")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + svn::Targets pathes(what); + ret = m_Data->m_Svnclient->update(pathes,rev, recurse?svn::DepthInfinity:svn::DepthFiles,false,false,true); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + removeFromUpdateCache(what,!recurse); + EMIT_REFRESH; + EMIT_FINISHED; +} + +/*! + \fn SvnActions::slotUpdateHeadRec() + */ +void SvnActions::slotUpdateHeadRec() +{ + prepareUpdate(false); +} + + +/*! + \fn SvnActions::prepareUpdate(bool ask) + */ +void SvnActions::prepareUpdate(bool ask) +{ + if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return; + SvnItemList k; + m_Data->m_ParentList->SelectionList(&k); + + QStringList what; + if (k.count()==0) { + what.append(m_Data->m_ParentList->baseUri()); + } else { + SvnItemListIterator liter(k); + SvnItem*cur; + while ((cur=liter.current())!=0){ + ++liter; + what.append(cur->fullName()); + } + } + svn::Revision r(svn::Revision::HEAD); + if (ask) { + Rangeinput_impl*rdlg; + KDialog*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true); + if (!dlg) { + return; + } + rdlg->setStartOnly(true); + /* just here cause layout has changed meanwhile */ + dlg->resize( QSize(120,60).expandedTo(dlg->minimumSizeHint()) ); + int result; + if ((result=dlg->exec())==QDialog::Accepted) { + Rangeinput_impl::revision_range range = rdlg->getRange(); + r=range.first; + } + delete dlg; + if (result!=QDialog::Accepted) return; + } + makeUpdate(what,r,true); +} + + +/*! + \fn SvnActions::slotUpdateTo() + */ +void SvnActions::slotUpdateTo() +{ + prepareUpdate(true); +} + + +/*! + \fn SvnActions::slotAdd() + */ +void SvnActions::slotAdd() +{ + makeAdd(false); +} + +void SvnActions::slotAddRec() +{ + makeAdd(true); +} + +void SvnActions::makeAdd(bool rec) +{ + if (!m_Data->m_CurrentContext) return; + if (!m_Data->m_ParentList) return; + QPtrList<SvnItem> lst; + m_Data->m_ParentList->SelectionList(&lst); + if (lst.count()==0) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Which files or directories should I add?")); + return; + } + QValueList<svn::Path> items; + SvnItemListIterator liter(lst); + SvnItem*cur; + while ((cur=liter.current())!=0){ + ++liter; + if (cur->isVersioned()) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("<center>The entry<br>%1<br>is versioned - break.</center>") + .arg(cur->fullName())); + return; + } + items.push_back(svn::Path(cur->fullName())); + } + addItems(items,rec?svn::DepthInfinity:svn::DepthEmpty); + liter.toFirst(); +#if 0 + while ((cur=liter.current())!=0){ + ++liter; + //cur->refreshStatus(); + + //emit sigRefreshCurrent(static_cast<FileListViewItem*>(cur->parent())); + } +#else + emit sigRefreshCurrent(0); +#endif +} + +bool SvnActions::addItems(const QStringList&w,svn::Depth depth) +{ + QValueList<svn::Path> items; + for (unsigned int i = 0; i<w.count();++i) { + items.push_back(w[i]); + } + return addItems(items,depth); +} + +bool SvnActions::addItems(const QValueList<svn::Path> &items,svn::Depth depth) +{ + QString ex; + try { + QValueList<svn::Path>::const_iterator piter; + for (piter=items.begin();piter!=items.end();++piter) { + m_Data->m_Svnclient->add((*piter),depth); + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +bool SvnActions::makeDelete(const QStringList&w) +{ + int answer = KMessageBox::questionYesNoList(0,i18n("Really delete these entries?"),w,i18n("Delete from repository")); + if (answer!=KMessageBox::Yes) { + return false; + } + svn::Pathes items; + for (unsigned int i = 0; i<w.count();++i) { + items.push_back(w[i]); + } + return makeDelete(items); +} + +/*! + \fn SvnActions::makeDelete() + */ +bool SvnActions::makeDelete(const svn::Pathes&items) +{ + if (!m_Data->m_CurrentContext) return false; + QString ex; + try { + svn::Targets target(items); + m_Data->m_Svnclient->remove(target,false); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + EMIT_FINISHED; + return true; +} + +void SvnActions::slotCheckout() +{ + CheckoutExport(false); +} + +void SvnActions::slotExport() +{ + CheckoutExport(true); +} + +void SvnActions::slotCheckoutCurrent() +{ + CheckoutExportCurrent(false); +} + +void SvnActions::slotExportCurrent() +{ + CheckoutExportCurrent(true); +} + +void SvnActions::CheckoutExport(bool _exp) +{ + CheckoutInfo_impl*ptr; + KDialogBase * dlg = createDialog(&ptr,(_exp?i18n("Export repository"):i18n("Checkout a repository")),true,"checkout_export_dialog"); + if (dlg) { + if (dlg->exec()==QDialog::Accepted) { + svn::Revision r = ptr->toRevision(); + bool openit = ptr->openAfterJob(); + bool ignoreExternal=ptr->ignoreExternals(); + makeCheckout(ptr->reposURL(),ptr->targetDir(),r,r, + ptr->getDepth(), + _exp, + openit, + ignoreExternal, + ptr->overwrite(),0); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"checkout_export_dialog",false); + delete dlg; + } +} + +void SvnActions::CheckoutExport(const QString&what,bool _exp,bool urlisTarget) +{ + CheckoutInfo_impl*ptr; + KDialog * dlg = createDialog(&ptr,_exp?i18n("Export a repository"):i18n("Checkout a repository"),true); + if (dlg) { + if (!urlisTarget) { + ptr->setStartUrl(what); + } else { + ptr->setTargetUrl(what); + } + if (dlg->exec()==QDialog::Accepted) { + svn::Revision r = ptr->toRevision(); + bool openIt = ptr->openAfterJob(); + bool ignoreExternal = ptr->ignoreExternals(); + makeCheckout(ptr->reposURL(),ptr->targetDir(),r,r,ptr->getDepth(),_exp,openIt,ignoreExternal,ptr->overwrite(),0); + } + delete dlg; + } +} + +void SvnActions::CheckoutExportCurrent(bool _exp) +{ + if ( !m_Data->m_ParentList || (!_exp&&m_Data->m_ParentList->isWorkingCopy()) ) return; + SvnItem*k = m_Data->m_ParentList->Selected(); + if (k && !k->isDir()) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),_exp?i18n("Exporting a file?"):i18n("Checking out a file?")); + return; + } + QString what; + if (!k) { + what = m_Data->m_ParentList->baseUri(); + } else { + what = k->fullName(); + } + CheckoutExport(what,_exp); +} + +bool SvnActions::makeCheckout(const QString&rUrl,const QString&tPath,const svn::Revision&r,const svn::Revision&_peg, + svn::Depth depth, + // kind of operation + bool _exp, + // open after job + bool openIt, + // ignore externals + bool ignoreExternal, + // overwrite/force not versioned items + bool overwrite, + QWidget*_p + ) +{ + QString fUrl = rUrl; + QString ex; + while (fUrl.endsWith("/")) { + fUrl.truncate(fUrl.length()-1); + } + svn::Path p(tPath); + svn::Revision peg = _peg; + if (r!=svn::Revision::BASE && r!=svn::Revision::WORKING && _peg==svn::Revision::UNDEFINED) { + peg = r; + } + if (!_exp||!m_Data->m_CurrentContext) reInitClient(); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,_p?_p:m_Data->m_ParentList->realWidget(),0,_exp?i18n("Export"):i18n("Checkout"),_exp?i18n("Exporting"):i18n("Checking out")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + if (_exp) { + /// @todo setup parameter for export operation + m_Data->m_Svnclient->doExport(svn::Path(fUrl),p,r,peg,overwrite,QString::null,ignoreExternal,depth); + } else { + m_Data->m_Svnclient->checkout(fUrl,p,r,peg,depth,ignoreExternal,overwrite); + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + if (openIt) { + if (!_exp) emit sigGotourl(tPath); + else kapp->invokeBrowser(tPath); + } + EMIT_FINISHED; + + return true; +} + +void SvnActions::slotRevert() +{ + if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return; + QPtrList<SvnItem> lst; + m_Data->m_ParentList->SelectionList(&lst); + QStringList displist; + SvnItemListIterator liter(lst); + SvnItem*cur; + if (lst.count()>0) { + while ((cur=liter.current())!=0){ + if (!cur->isVersioned()) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("<center>The entry<br>%1<br>is not versioned - break.</center>") + .arg(cur->fullName())); + return; + } + displist.append(cur->fullName()); + ++liter; + } + } else { + displist.push_back(m_Data->m_ParentList->baseUri()); + } + slotRevertItems(displist); + EMIT_REFRESH; +} + +void SvnActions::slotRevertItems(const QStringList&displist) +{ + if (!m_Data->m_CurrentContext) return; + if (displist.count()==0) { + return; + } + + svn::Depth depth; + RevertFormImpl*ptr; + KDialog * dlg = createDialog(&ptr,i18n("Revert entries"),true); + if (!dlg) { + return; + } + ptr->setDispList(displist); + if (dlg->exec()!=QDialog::Accepted) { + delete dlg; + return; + } + depth = ptr->getDepth(); + + QValueList<svn::Path> items; + for (unsigned j = 0; j<displist.count();++j) { + items.push_back(svn::Path((*(displist.at(j))))); + } + QString ex; + + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Revert"),i18n("Reverting items")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + svn::Targets target(items); + m_Data->m_Svnclient->revert(target,depth); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + // remove them from cache + for (unsigned int j = 0; j<items.count();++j) { + m_Data->m_Cache.deleteKey(items[j].path(),depth!=svn::DepthInfinity); +// m_Data->m_Cache.dump_tree(); + } + EMIT_FINISHED; +} + +bool SvnActions::makeSwitch(const QString&rUrl,const QString&tPath,const svn::Revision&r,svn::Depth depth,const svn::Revision&peg,bool stickydepth,bool ignore_externals,bool allow_unversioned) +{ + if (!m_Data->m_CurrentContext) return false; + QString fUrl = rUrl; + QString ex; + while (fUrl.endsWith("/")) { + fUrl.truncate(fUrl.length()-1); + } + svn::Path p(tPath); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Switch url"),i18n("Switching url")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->doSwitch(p,fUrl,r,depth,peg,stickydepth,ignore_externals,allow_unversioned); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + EMIT_FINISHED; + return true; +} + +bool SvnActions::makeRelocate(const QString&fUrl,const QString&tUrl,const QString&path,bool rec) +{ + if (!m_Data->m_CurrentContext) return false; + QString _f = fUrl; + QString _t = tUrl; + QString ex; + while (_f.endsWith("/")) { + _f.truncate(_f.length()-1); + } + while (_t.endsWith("/")) { + _t.truncate(_t.length()-1); + } + svn::Path p(path); + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Relocate url"),i18n("Relocate repository to new URL")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->relocate(p,_f,_t,rec); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + EMIT_FINISHED; + return true; +} + +void SvnActions::slotSwitch() +{ + if (!m_Data->m_CurrentContext) return; + if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return; + + QPtrList<SvnItem> lst; + m_Data->m_ParentList->SelectionList(&lst); + + if (lst.count()>1) { + KMessageBox::error(0,i18n("Can only switch one item at time")); + return; + } + SvnItem*k; + + k = m_Data->m_ParentList->SelectedOrMain(); + if (!k) { + KMessageBox::error(0,i18n("Error getting entry to switch")); + return; + } + QString path,what; + path = k->fullName(); + what = k->Url(); + if (makeSwitch(path,what)) { + emit reinitItem(k); + } +} + +bool SvnActions::makeSwitch(const QString&path,const QString&what) +{ + CheckoutInfo_impl*ptr; + KDialogBase * dlg = createDialog(&ptr,i18n("Switch url"),true,"switch_url_dlg"); + bool done = false; + if (dlg) { + ptr->setStartUrl(what); + ptr->disableAppend(true); + ptr->disableTargetDir(true); + ptr->disableOpen(true); + if (dlg->exec()==QDialog::Accepted) { + svn::Revision r = ptr->toRevision(); + done = makeSwitch(ptr->reposURL(),path,r,ptr->getDepth(),r,true,ptr->ignoreExternals(),ptr->overwrite()); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"switch_url_dlg",false); + delete dlg; + } + return done; +} + +bool SvnActions::makeCleanup(const QString&path) +{ + if (!m_Data->m_CurrentContext) return false; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Cleanup"),i18n("Cleaning up folder")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->cleanup(svn::Path(path)); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +void SvnActions::slotResolved(const QString&path) +{ + if (!m_Data->m_CurrentContext) return; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Resolve"),i18n("Marking resolved")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->resolve(svn::Path(path),svn::DepthEmpty); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + m_Data->m_conflictCache.deleteKey(path,false); +} + +void SvnActions::slotResolve(const QString&p) +{ + if (!m_Data->m_CurrentContext) return; + QString eresolv = Kdesvnsettings::conflict_resolver(); + QStringList wlist = QStringList::split(" ",eresolv); + if (wlist.size()==0) { + return; + } + kdDebug()<<"Resolve: "<<p<<endl; + svn::InfoEntry i1; + if (!singleInfo(p,svn::Revision::UNDEFINED,i1)) { + return; + } + QFileInfo fi(p); + QString base = fi.dirPath(true); + kdDebug()<<i1.conflictNew()<<" " + <<i1.conflictOld()<<" " + <<i1.conflictWrk()<<" " + <<endl; + if (!i1.conflictNew().length()|| + !i1.conflictOld().length()|| + !i1.conflictWrk().length() ) { + emit sendNotify(i18n("Could not retrieve conflict information - giving up.")); + return; + } + + KProcess*proc = new KProcess(); + for ( QStringList::Iterator it = wlist.begin();it!=wlist.end();++it) { + if (*it=="%o"||*it=="%l") { + *proc<<(base+"/"+i1.conflictOld()); + } else if (*it=="%m" || *it=="%w") { + *proc<<(base+"/"+i1.conflictWrk()); + } else if (*it=="%n"||*it=="%r") { + *proc<<(base+"/"+i1.conflictNew()); + } else if (*it=="%t") { + *proc<<p; + } else { + *proc << *it; + } + } + connect(proc,SIGNAL(processExited(KProcess*)),this,SLOT(procClosed(KProcess*))); + connect(proc,SIGNAL(receivedStderr(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + connect(proc,SIGNAL(receivedStdout(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + if (proc->start(m_Data->runblocked?KProcess::Block:KProcess::NotifyOnExit,KProcess::All)) { + return; + } else { + emit sendNotify(i18n("Resolve-process could not started, check command.")); + } + delete proc; + return; +} + +void SvnActions::slotImport(const QString&path,const QString&target,const QString&message,svn::Depth depth, + bool noIgnore,bool noUnknown) +{ + if (!m_Data->m_CurrentContext) return; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Import"),i18n("Importing items")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->import(svn::Path(path),target,message,depth,noIgnore,noUnknown); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } +} + +void SvnActions::slotMergeExternal(const QString&_src1,const QString&_src2, const QString&_target, + const svn::Revision&rev1,const svn::Revision&rev2,const svn::Revision&_peg,bool rec) +{ + KTempDir tdir1; + tdir1.setAutoDelete(true); + QString src1 = _src1; + QString src2 = _src2; + QString target = _target; + bool singleMerge = false; + + if (rev1 == rev2 && (src2.isEmpty() || src1==src2) ) { + singleMerge = true; + } + if (src1.isEmpty()) { + emit clientException(i18n("Nothing to merge.")); + return; + } + if (target.isEmpty()) { + emit clientException(i18n("No destination to merge.")); + return; + } + + KURL url(target); + if (!url.isLocalFile()) { + emit clientException(i18n("Target for merge must be local!")); + return; + } + + QFileInfo f1(src1); + QFileInfo f2(src2); + bool isDir = true; + + svn::InfoEntry i1,i2; + + if (!singleInfo(src1,rev1,i1)) { + return; + } + isDir = i1.isDir(); + if (!singleMerge && src1 != src2) { + if (!singleInfo(src2,rev2,i2)) { + return; + } + if (i2.isDir()!=isDir) { + emit clientException(i18n("Both sources must be same type!")); + return; + } + } + + QFileInfo ti(target); + + if (ti.isDir()!=isDir) { + emit clientException(i18n("Target for merge must same type like sources!")); + return; + } + + QString s1 = f1.fileName()+"-"+rev1.toString(); + QString s2 = f2.fileName()+"-"+rev2.toString(); + QString first,second,out; + if (rev1 != svn::Revision::WORKING) { + first = tdir1.name()+"/"+s1; + } else { + first = src1; + } + if (!singleMerge) { + if (rev2!=svn::Revision::WORKING) { + second = tdir1.name()+"/"+s2; + } else { + second = src2; + } + } else { + // only two-way merge + second = QString::null; + } + if (second == first) { + KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Both entries seems to be the same, won't do a merge.")); + return; + } + + if (rev1 != svn::Revision::WORKING) { + if (isDir) { + if (!makeCheckout(src1,first,rev1,svn::Revision::UNDEFINED, + rec?svn::DepthInfinity:svn::DepthFiles, + true, + false, + false, + false,0)) { + return; + } + } else { + if (!get(src1,first,rev1,svn::Revision::UNDEFINED,m_Data->m_ParentList->realWidget())) { + return; + } + } + } + + if (!singleMerge) { + if (rev2!=svn::Revision::WORKING) { + if (isDir) { + if (!makeCheckout(src2,second,rev2,svn::Revision::UNDEFINED, + rec?svn::DepthInfinity:svn::DepthFiles, + true,false,false,false,0)) { + return; + } + } else { + if (!get(src2,second,rev2,svn::Revision::UNDEFINED,m_Data->m_ParentList->realWidget())) { + return; + } + } + } + } + QString edisp = Kdesvnsettings::external_merge_program(); + QStringList wlist = QStringList::split(" ",edisp); + KProcess*proc = new KProcess(); + for ( QStringList::Iterator it = wlist.begin();it!=wlist.end();++it) { + if (*it=="%s1") { + *proc<<first; + } else if (*it=="%s2") { + if (!second.isEmpty()) *proc<<second; + } else if (*it=="%t") { + *proc<<target; + } else { + *proc << *it; + } + } + connect(proc,SIGNAL(processExited(KProcess*)),this,SLOT(procClosed(KProcess*))); + connect(proc,SIGNAL(receivedStderr(KProcess*,char*,int)),this,SLOT(receivedStderr(KProcess*,char*,int))); + if (proc->start(m_Data->runblocked?KProcess::Block:KProcess::NotifyOnExit,KProcess::Stderr)) { + if (!m_Data->runblocked) { + tdir1.setAutoDelete(false); + m_Data->m_tempdirlist[proc].append(tdir1.name()); + } + return; + } else { + emit sendNotify(i18n("Merge-process could not started, check command.")); + } + delete proc; +} + +void SvnActions::slotMergeWcRevisions(const QString&_entry,const svn::Revision&rev1, + const svn::Revision&rev2, + bool rec,bool ancestry,bool forceIt,bool dry) +{ + slotMerge(_entry,_entry,_entry,rev1,rev2,svn::Revision::UNDEFINED,rec,ancestry,forceIt,dry); +} + +void SvnActions::slotMerge(const QString&src1,const QString&src2, const QString&target, + const svn::Revision&rev1,const svn::Revision&rev2,const svn::Revision&_peg, + bool rec,bool ancestry,bool forceIt,bool dry) +{ + if (!m_Data->m_CurrentContext) return; + QString s2; + + svn::Revision peg = svn::Revision::HEAD; + svn::Revision tpeg; + svn::RevisionRanges ranges; + svn::Path p1; + try { + svn::Path::parsePeg(src1,p1,tpeg); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + if (tpeg!=svn::Revision::UNDEFINED) { + peg=tpeg; + } + svn::Path p2(src2); + + bool pegged_merge=false; + + if(!p2.isset() || src1==src2) { + // pegged merge + pegged_merge=true; + ranges.append(svn::RevisionRange(rev1,rev2)); + if (peg==svn::Revision::UNDEFINED) { + if (p1.isUrl()) { + peg = rev2; + } else { + peg=svn::Revision::WORKING; + } + } + } + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Merge"),i18n("Merging items")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + if (pegged_merge) { + m_Data->m_Svnclient->merge_peg(p1,ranges,svn::Revision::HEAD,svn::Path(target),rec?svn::DepthUnknown:svn::DepthFiles, + ancestry,dry,forceIt,false); + } else { + m_Data->m_Svnclient->merge(p1,rev1,p2,rev2, + svn::Path(target), + forceIt,rec?svn::DepthUnknown:svn::DepthFiles,ancestry,dry); + } + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } +} + +/*! + \fn SvnActions::slotCopyMove(bool,const QString&,const QString&) + */ +bool SvnActions::makeMove(const QString&Old,const QString&New,bool force) +{ + if (!m_Data->m_CurrentContext) return false; + svn::Revision nnum; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Move"),i18n("Moving/Rename item ")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + nnum = m_Data->m_Svnclient->move(svn::Path(Old),svn::Path(New),force); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + if (nnum != svn::Revision::UNDEFINED) { + emit sendNotify(i18n("Committed revision %1.").arg(nnum.toString())); + } + EMIT_REFRESH; + return true; +} + +bool SvnActions::makeMove(const KURL::List&Old,const QString&New,bool force) +{ + svn::Revision nnum; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Move"),i18n("Moving entries")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + KURL::List::ConstIterator it = Old.begin(); + bool local = false; + + if ((*it).protocol().isEmpty()) { + local = true; + } + it = Old.begin(); + svn::Pathes p; + for (;it!=Old.end();++it) { + p.append((local?(*it).path():(*it).url())); + } + svn::Targets t(p); + svn::Path NPath(New); + m_Data->m_Svnclient->move(t,NPath,force,true,false); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +bool SvnActions::makeCopy(const QString&Old,const QString&New,const svn::Revision&rev) +{ + if (!m_Data->m_CurrentContext) return false; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Copy / Move"),i18n("Copy or Moving entries")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + m_Data->m_Svnclient->copy(svn::Path(Old),rev,svn::Path(New)); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + EMIT_REFRESH; + return true; +} + +bool SvnActions::makeCopy(const KURL::List&Old,const QString&New,const svn::Revision&rev) +{ + KURL::List::ConstIterator it = Old.begin(); + svn::Pathes p; + bool local = false; + if ((*it).protocol().isEmpty()) { + local = true; + } + for (;it!=Old.end();++it) { + p.append((local?(*it).path():(*it).url())); + } + svn::Targets t(p); + + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Copy / Move"),i18n("Copy or Moving entries")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + KURL::List::ConstIterator it = Old.begin(); + m_Data->m_Svnclient->copy(t,rev,rev,svn::Path(New),true); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +/*! + \fn SvnActions::makeLock(const QStringList&) + */ +void SvnActions::makeLock(const QStringList&what,const QString&_msg,bool breakit) +{ + QValueList<svn::Path> targets; + for (unsigned int i = 0; i<what.count();++i) { + targets.push_back(svn::Path((*(what.at(i))))); + } + if (!m_Data->m_CurrentContext) return; + try { + m_Data->m_Svnclient->lock(svn::Targets(targets),_msg,breakit); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } +} + + +/*! + \fn SvnActions::makeUnlock(const QStringList&) + */ +void SvnActions::makeUnlock(const QStringList&what,bool breakit) +{ + QValueList<svn::Path> targets; + if (!m_Data->m_CurrentContext) return; + for (unsigned int i = 0; i<what.count();++i) { + targets.push_back(svn::Path((*(what.at(i))))); + } + + try { + m_Data->m_Svnclient->unlock(svn::Targets(targets),breakit); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return; + } + for (unsigned int i = 0; i<what.count();++i) { + m_Data->m_repoLockCache.deleteKey(*(what.at(i)),true); + } +// m_Data->m_repoLockCache.dump_tree(); +} + + +/*! + \fn SvnActions::makeStatus(const QString&what, svn::StatusEntries&dlist) + */ +bool SvnActions::makeStatus(const QString&what, svn::StatusEntries&dlist, svn::Revision&where,bool rec,bool all) +{ + bool display_ignores = Kdesvnsettings::display_ignored_files(); + return makeStatus(what,dlist,where,rec,all,display_ignores); +} + +bool SvnActions::makeStatus(const QString&what, svn::StatusEntries&dlist, svn::Revision&where,bool rec,bool all,bool display_ignores,bool updates) +{ + bool disp_remote_details = Kdesvnsettings::details_on_remote_listing(); + QString ex; + svn::Depth _d=rec?svn::DepthInfinity:svn::DepthImmediates; + try { + StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Status / List"),i18n("Creating list / check status")); + connect(this,SIGNAL(sigExtraLogMsg(const QString&)),&sdlg,SLOT(slotExtraMessage(const QString&))); + // rec all up noign + dlist = m_Data->m_Svnclient->status(what,_d,all,updates,display_ignores,where,disp_remote_details,false); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +void SvnActions::checkAddItems(const QString&path,bool print_error_box) +{ + svn::StatusEntries dlist; + svn::StatusEntries rlist; + QStringList displist; + svn::Revision where = svn::Revision::HEAD; + if (!makeStatus(path,dlist,where,true,true,false,false)) { + return; + } + for (unsigned int i = 0; i<dlist.size();++i) { + if (!dlist[i]->isVersioned()) { + rlist.append(dlist[i]); + displist.append(dlist[i]->path()); + } + } + if (rlist.size()==0) { + if (print_error_box) KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("No unversioned items found.")); + } else { + KListView*ptr; + KDialogBase * dlg = createDialog(&ptr,i18n("Add unversioned items"),true,"add_items_dlg"); + ptr->addColumn("Item"); + for (unsigned j = 0; j<displist.size();++j) { + QCheckListItem * n = new QCheckListItem(ptr,displist[j],QCheckListItem::CheckBox); + n->setOn(true); + } + if (dlg->exec()==QDialog::Accepted) { + QListViewItemIterator it(ptr); + displist.clear(); + while(it.current()) { + QCheckListItem*t = (QCheckListItem*)it.current(); + if (t->isOn()) { + displist.append(t->text()); + } + ++it; + } + if (displist.count()>0) { + addItems(displist,svn::DepthEmpty); + } + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"add_items_dlg",false); + delete dlg; + } +} + +void SvnActions::stopCheckModThread() +{ + m_Data->m_ThreadCheckTimer.stop(); + if (m_CThread) { + m_CThread->cancelMe(); + if (!m_CThread->wait(MAX_THREAD_WAITTIME)) { + m_CThread->terminate(); + m_CThread->wait(MAX_THREAD_WAITTIME); + } + delete m_CThread; + m_CThread=0; + } +} + +void SvnActions::stopCheckUpdateThread() +{ + m_Data->m_UpdateCheckTimer.stop(); + if (m_UThread) { + m_UThread->cancelMe(); + if (!m_UThread->wait(MAX_THREAD_WAITTIME)) { + m_UThread->terminate(); + m_UThread->wait(MAX_THREAD_WAITTIME); + } + delete m_UThread; + m_UThread=0; + } +} + +void SvnActions::stopFillCache() +{ + if (m_FCThread) { + m_FCThread->cancelMe(); + if (!m_FCThread->wait(MAX_THREAD_WAITTIME)) { + m_FCThread->terminate(); + m_FCThread->wait(MAX_THREAD_WAITTIME); + } + delete m_FCThread; + m_FCThread = 0; + emit sigCacheStatus(-1,-1); + } +} + +void SvnActions::stopMain() +{ + if (m_Data->m_CurrentContext) { + m_Data->m_SvnContextListener->setCanceled(true); + sleep(1); + m_Data->m_SvnContextListener->contextCancel(); + } +} + +void SvnActions::killallThreads() +{ + stopMain(); + stopCheckModThread(); + stopCheckUpdateThread(); + stopFillCache(); +} + +bool SvnActions::createModifiedCache(const QString&what) +{ + stopCheckModThread(); + m_Data->m_Cache.clear(); + m_Data->m_conflictCache.clear(); + kdDebug()<<"Create cache for " << what << endl; + m_CThread = new CheckModifiedThread(this,what); + m_CThread->start(); + m_Data->m_ThreadCheckTimer.start(100,true); + return true; +} + +void SvnActions::checkModthread() +{ + if (!m_CThread)return; + if (m_CThread->running()) { + m_Data->m_ThreadCheckTimer.start(100,true); + return; + } + kdDebug()<<"ModifiedThread seems stopped"<<endl; + for (unsigned int i = 0; i < m_CThread->getList().count();++i) { + svn::StatusPtr ptr = m_CThread->getList()[i]; + if (m_CThread->getList()[i]->isRealVersioned()&& ( + m_CThread->getList()[i]->textStatus()==svn_wc_status_modified|| + m_CThread->getList()[i]->textStatus()==svn_wc_status_added|| + m_CThread->getList()[i]->textStatus()==svn_wc_status_deleted|| + m_CThread->getList()[i]->textStatus()==svn_wc_status_replaced|| + m_CThread->getList()[i]->propStatus()==svn_wc_status_modified + ) ) { + m_Data->m_Cache.insertKey(ptr,ptr->path()); + } else if (m_CThread->getList()[i]->textStatus()==svn_wc_status_conflicted) { + m_Data->m_conflictCache.insertKey(ptr,ptr->path()); + } + } + delete m_CThread; + m_CThread = 0; + emit sigRefreshIcons(false); +} + +void SvnActions::checkUpdateThread() +{ + if (!m_UThread)return; + if (m_UThread->running()) { + if (m_Data->m_UpdateCheckTick.elapsed()>2500) { + m_Data->m_UpdateCheckTick.restart(); + emit sendNotify(i18n("Still checking for updates")); + } + m_Data->m_UpdateCheckTimer.start(100,true); + return; + } + kdDebug()<<"Updates Thread seems stopped"<<endl; + + bool newer=false; + for (unsigned int i = 0; i < m_UThread->getList().count();++i) { + svn::StatusPtr ptr = m_UThread->getList()[i]; + if (ptr->validReposStatus()) { + m_Data->m_UpdateCache.insertKey(ptr,ptr->path()); + ptr->textStatus(); + ptr->propStatus(); + if (!(ptr->validLocalStatus())) { + newer = true; + } + } + if (ptr->isLocked() && + !(ptr->entry().lockEntry().Locked())) { + m_Data->m_repoLockCache.insertKey(ptr,ptr->path()); + } + } + emit sigRefreshIcons(newer); + emit sendNotify(i18n("Checking for updates finished")); + if (newer) { + emit sendNotify(i18n("There are new items in repository")); + } + delete m_UThread; + m_UThread = 0; +} + +void SvnActions::getaddedItems(const QString&path,svn::StatusEntries&target) +{ + helpers::ValidRemoteOnly vro; + m_Data->m_UpdateCache.listsubs_if(path,vro); + target=vro.liste(); +} + +bool SvnActions::checkUpdatesRunning() +{ + return m_UThread && m_UThread->running(); +} + +void SvnActions::addModifiedCache(const svn::StatusPtr&what) +{ + if (what->textStatus()==svn_wc_status_conflicted) { + m_Data->m_conflictCache.insertKey(what,what->path()); + } else { + m_Data->m_Cache.insertKey(what,what->path()); +// m_Data->m_Cache.dump_tree(); + } +} + +void SvnActions::deleteFromModifiedCache(const QString&what) +{ + m_Data->m_Cache.deleteKey(what,true); + m_Data->m_conflictCache.deleteKey(what,true); + //m_Data->m_Cache.dump_tree(); +} + +bool SvnActions::checkModifiedCache(const QString&path) +{ + return m_Data->m_Cache.find(path); +} + +bool SvnActions::checkReposLockCache(const QString&path) +{ + return m_Data->m_repoLockCache.findSingleValid(path,false); +} + +bool SvnActions::checkReposLockCache(const QString&path,svn::SharedPointer<svn::Status>&t) +{ + /// @todo create a method where svn::Status* will be a parameter so no copy is needed but just reading content + return m_Data->m_repoLockCache.findSingleValid(path,t); +} + +bool SvnActions::checkConflictedCache(const QString&path) +{ + return m_Data->m_conflictCache.find(path); +} + +void SvnActions::startFillCache(const QString&path) +{ + stopFillCache(); + svn::InfoEntry e; + if (!doNetworking()) { + emit sendNotify(i18n("Not filling logcache because networking is disabled")); + return; + } + if (!singleInfo(path,svn::Revision::UNDEFINED,e)) { + return; + } + if (svn::Url::isLocal(e.reposRoot())) { + return; + } + m_FCThread=new FillCacheThread(this,e.reposRoot()); + m_FCThread->start(); + emit sendNotify(i18n("Filling log cache in background")); +} + +bool SvnActions::doNetworking() +{ + // if networking is allowd we don't need extra checks, second is just for avoiding segfaults + if (Kdesvnsettings::network_on()||!m_Data->m_ParentList) { + return true; + } + bool is_url=false; + if (m_Data->m_ParentList->isNetworked()) { + // if called http:// etc.pp. + is_url=true; + } else if (m_Data->m_ParentList->baseUri().startsWith("/")){ + // if opened a working copy we must check if it points to a networking repository + svn::InfoEntry e; + if (!singleInfo(m_Data->m_ParentList->baseUri(),svn::Revision::UNDEFINED,e)) { + return false; + } + is_url = !e.reposRoot().startsWith("file:/"); + } + return !is_url; +} + +void SvnActions::customEvent(QCustomEvent * e) +{ + if (e->type()==EVENT_LOGCACHE_FINISHED) { + emit sendNotify(i18n("Filling log cache in background finished.")); + stopFillCache(); + emit sigThreadsChanged(); + return; + } else if (e&&e->type()==EVENT_LOGCACHE_STATUS && m_FCThread && m_FCThread->running()) { + FillCacheStatusEvent*fev=(FillCacheStatusEvent*)e; + emit sigCacheStatus(fev->current(),fev->max()); + } +} + +/*! + \fn SvnActions::createUpdateCache(const QString&what) + */ +bool SvnActions::createUpdateCache(const QString&what) +{ + clearUpdateCache(); + m_Data->m_repoLockCache.clear(); + stopCheckUpdateThread(); + if (!doNetworking()) { + emit sendNotify(i18n("Not checking for updates because networking is disabled")); + return false; + } + + m_UThread = new CheckModifiedThread(this,what,true); + m_UThread->start(); + m_Data->m_UpdateCheckTimer.start(100,true); + emit sendNotify(i18n("Checking for updates started in background")); + m_Data->m_UpdateCheckTick.start(); + return true; +} + +bool SvnActions::checkUpdateCache(const QString&path)const +{ + return m_Data->m_UpdateCache.find(path); +} + +void SvnActions::removeFromUpdateCache(const QStringList&what,bool exact_only) +{ + for (unsigned int i = 0; i < what.count(); ++i) { + m_Data->m_UpdateCache.deleteKey(what[i],exact_only); + } +} + +bool SvnActions::isUpdated(const QString&path)const +{ + svn::SharedPointer<svn::Status> d; + return m_Data->m_UpdateCache.findSingleValid(path,d); +} + +bool SvnActions::getUpdated(const QString&path,svn::SharedPointer<svn::Status>&d)const +{ + return m_Data->m_UpdateCache.findSingleValid(path,d); +} + +void SvnActions::clearUpdateCache() +{ + m_Data->m_UpdateCache.clear(); +} + +/*! + \fn SvnActions::makeIgnoreEntry(const QString&which) + */ +bool SvnActions::makeIgnoreEntry(SvnItem*which,bool unignore) +{ + if (!which) return false; + QString parentName = which->getParentDir(); + if (parentName.isEmpty()) return false; + QString name = which->shortName(); + QString ex; + svn::Path p(parentName); + svn::Revision r(svn_opt_revision_unspecified); + + QPair<QLONG,svn::PathPropertiesMapList> pmp; + try { + pmp = m_Data->m_Svnclient->propget("svn:ignore",p,r,r); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + svn::PathPropertiesMapList pm = pmp.second; + QString data = ""; + if (pm.size()>0) { + svn::PropertiesMap&mp = pm[0].second; + data = mp["svn:ignore"]; + } + bool result = false; + QStringList lst = QStringList::split("\n",data); + QStringList::iterator it = lst.find(name); + if (it != lst.end()) { + if (unignore) { + lst.erase(it); + result = true; + } + } else { + if (!unignore) { + lst.append(name); + result = true; + } + } + if (result) { + data = lst.join("\n"); + try { + m_Data->m_Svnclient->propset("svn:ignore",data,p); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + } + return result; +} + +svn::PathPropertiesMapListPtr SvnActions::propList(const QString&which,const svn::Revision&where,bool cacheOnly) +{ + svn::PathPropertiesMapListPtr pm; + if (!which.isEmpty()) { + QString fk=where.toString()+"/"+which; + QString ex; + svn::Path p(which); + + if (where != svn::Revision::WORKING) + { + m_Data->m_PropertiesCache.findSingleValid(fk,pm); + } + if (!pm && !cacheOnly) + { + try { + pm = m_Data->m_Svnclient->proplist(p,where,where); + } catch (const svn::Exception&e) { + /* no messagebox needed */ + if (e.apr_err()!=SVN_ERR_WC_NOT_DIRECTORY) { + sendNotify(e.msg()); + } + } + if (where != svn::Revision::WORKING && pm) { + kdDebug()<<"Put into cache "<<endl; + m_Data->m_PropertiesCache.insertKey(pm,fk); + } + } + } + return pm; +} + +bool SvnActions::isLockNeeded(SvnItem*which,const svn::Revision&where) +{ + if (!which) return false; + QString ex; + svn::Path p(which->fullName()); + + QPair<QLONG,svn::PathPropertiesMapList> pmp; + try { + pmp = m_Data->m_Svnclient->propget("svn:needs-lock",p,where,where); + } catch (const svn::Exception&e) { + /* no messagebox needed */ + //emit clientException(e.msg()); + return false; + } + svn::PathPropertiesMapList pm = pmp.second; + if (pm.size()>0) { + svn::PropertiesMap&mp = pm[0].second; + if (mp.find("svn:needs-lock")!=mp.end()) { + return true; + } + } + return false; +} + +QString SvnActions::searchProperty(QString&Store, const QString&property, const QString&start,const svn::Revision&where,bool up) +{ + svn::Path pa(start); + kdDebug()<<"Url? "<<pa.isUrl()<<endl; + svn::InfoEntry inf; + + if (!singleInfo(start,where,inf)) { + return QString::null; + } + while(pa.length()>0) { + svn::PathPropertiesMapListPtr pm = propList(pa,where,false); + if (!pm) { + return QString::null; + } + if (pm->size()>0) { + svn::PropertiesMap&mp = (*pm)[0].second; + if (mp.find(property)!=mp.end()) { + Store=mp[property]; + return pa; + } + } + if (up) { + pa.removeLast(); + kdDebug()<<"Going up to " << pa.path() << endl; + if (pa.isUrl() && inf.reposRoot().length()>pa.path().length()) { + kdDebug()<<pa.path()<<" is not in repository" << endl; + break; + } + + } else { + break; + } + } + return QString::null; +} + +bool SvnActions::makeList(const QString&url,svn::DirEntries&dlist,svn::Revision&where,bool rec) +{ + if (!m_Data->m_CurrentContext) return false; + QString ex; + try { + dlist = m_Data->m_Svnclient->list(url,where,where,rec?svn::DepthInfinity:svn::DepthEmpty,false); + } catch (const svn::Exception&e) { + emit clientException(e.msg()); + return false; + } + return true; +} + +/*! + \fn SvnActions::isLocalWorkingCopy(const KURL&url) + */ +bool SvnActions::isLocalWorkingCopy(const KURL&url,QString&_baseUri) +{ + if (url.isEmpty()||!url.isLocalFile()) return false; + QString cleanpath = url.path(); + while (cleanpath.endsWith("/")) { + cleanpath.truncate(cleanpath.length()-1); + } + _baseUri=""; + svn::Revision peg(svn_opt_revision_unspecified); + svn::Revision rev(svn_opt_revision_unspecified); + svn::InfoEntries e; + try { + e = m_Data->m_Svnclient->info(cleanpath,svn::DepthEmpty,rev,peg); + } catch (const svn::Exception&e) { + kdDebug()<< e.msg()<< " " << endl; + if (SVN_ERR_WC_NOT_DIRECTORY==e.apr_err()) + { + return false; + } + return true; + } + _baseUri=e[0].url(); + return true; +} + +void SvnActions::slotExtraLogMsg(const QString&msg) +{ + emit sigExtraLogMsg(msg); +} + +void SvnActions::slotCancel(bool how) +{ + if (!m_Data->m_CurrentContext) return; + m_Data->m_SvnContextListener->setCanceled(how); +} + +void SvnActions::setContextData(const QString&aKey,const QString&aValue) +{ + if (aValue.isNull()) { + QMap<QString,QString>::iterator it = m_Data->m_contextData.find(aKey); + if (it!=m_Data->m_contextData.end()) { + m_Data->m_contextData.remove(it); + } + } else { + m_Data->m_contextData[aKey]=aValue; + } +} + +void SvnActions::clearContextData() +{ + m_Data->m_contextData.clear(); +} + +QString SvnActions::getContextData(const QString&aKey)const +{ + if (m_Data->m_contextData.find(aKey)!=m_Data->m_contextData.end()) { + return m_Data->m_contextData[aKey]; + } + return QString::null; +} + +bool SvnActions::threadRunning(ThreadType which) +{ + switch(which) { + case checkupdatethread: + return (m_UThread && m_UThread->running()); + break; + case fillcachethread: + return (m_FCThread && m_FCThread->running()); + break; + case checkmodifiedthread: + return (m_CThread && m_CThread->running()); + break; + } + return false; +} + +#include "svnactions.moc" diff --git a/src/svnfrontend/svnactions.h b/src/svnfrontend/svnactions.h new file mode 100644 index 0000000..96a2b5e --- /dev/null +++ b/src/svnfrontend/svnactions.h @@ -0,0 +1,254 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNACTIONS_H +#define SVNACTIONS_H + +#include "src/svnqt/client.hpp" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/smart_pointer.hpp" +#include "src/svnqt/shared_pointer.hpp" +#include "src/svnqt/svnqttypes.hpp" + +#include "simple_logcb.h" + +#include <kurl.h> +#include <kguiitem.h> + +#include <qobject.h> +#include <qdatetime.h> +#include <qstringlist.h> + +class ItemDisplay; +class SvnItem; +class KDialog; +class KDialogBase; +class QDialog; +class CContextListener; +class KProcess; +class SvnActionsData; +class CheckModifiedThread; +class CheckUpdatesThread; +class FillCacheThread; + +namespace svn { + class Context; + class LogEntry; + class InfoEntry; +} + +namespace KIO { + class Job; +} + +/** +@author Rajko Albrecht +*/ +class SvnActions : public QObject,public SimpleLogCb +{ + Q_OBJECT +public: + enum ThreadType { + checkupdatethread, + fillcachethread, + checkmodifiedthread + }; + + SvnActions(ItemDisplay *parent, const char *name = 0,bool processes_blocked=false); + ~SvnActions(); + void reInitClient(); + //svn::Client&svnClient(){return m_Svnclient;} + svn::Client* svnclient(); + void prepareUpdate(bool ask); + template<class T> KDialogBase* createDialog(T**ptr,const QString&_head,bool OkCance=false, + const char*name="standard_dialog", + bool showHelp=false,bool modal=true, + const KGuiItem&u1 = KGuiItem()); + + bool makeGet(const svn::Revision&start, const QString&what,const QString&target, + const svn::Revision&peg=svn::Revision::UNDEFINED,QWidget*dlgparent=0); + + + bool addItems(const QValueList<svn::Path> &items,svn::Depth depth=svn::DepthEmpty); + bool addItems(const QStringList&w,svn::Depth depth=svn::DepthEmpty); + void checkAddItems(const QString&path,bool print_error_box=true); + + bool makeDelete(const svn::Pathes&); + bool makeDelete(const QStringList&); + void makeLock(const QStringList&,const QString&,bool); + void makeUnlock(const QStringList&,bool); + + bool makeStatus(const QString&what, svn::StatusEntries&dlist, svn::Revision&where, bool rec=false,bool all=true); + bool makeStatus(const QString&what, svn::StatusEntries&dlist, svn::Revision&where, bool rec,bool all,bool display_ignored,bool updates=false); + bool makeList(const QString&url,svn::DirEntries&dlist,svn::Revision&where,bool rec=false); + + bool createModifiedCache(const QString&base); + bool checkModifiedCache(const QString&path); + bool checkConflictedCache(const QString&path); + bool checkReposLockCache(const QString&path); + bool checkReposLockCache(const QString&path,svn::SharedPointer<svn::Status>&t); + void addModifiedCache(const svn::StatusPtr&what); + void deleteFromModifiedCache(const QString&what); + + bool makeIgnoreEntry(SvnItem*which,bool unignore); + bool isLockNeeded(SvnItem*which,const svn::Revision&where); + QString searchProperty(QString&store, const QString&property, const QString&start,const svn::Revision&where,bool up=false); + svn::PathPropertiesMapListPtr propList(const QString&which,const svn::Revision&where,bool cacheOnly); + + bool changeProperties(const svn::PropertiesMap&setList,const QValueList<QString>&,const QString&path); + + //! generate and displays a revision tree + /*! + * the parameter @a what must prepared, eg, if it comes from working copy + * it must not contain a "file://" inside. + * \param what item to display + * \param rev Revision the item-path is available, intersting only when @a what is a repository item + * \param startr startrevision for log + * \param endr endrevision for log + */ + void makeTree(const QString&what,const svn::Revision&rev, + const svn::Revision&startr=svn::Revision(1), + const svn::Revision&endr=svn::Revision::HEAD); + void makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,SvnItem*k,bool list_files=false,int limit = 0); + void makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,const QString&,bool list_files=false, int limit=0); + svn::SharedPointer<svn::LogEntriesMap> getLog(const svn::Revision&start,const svn::Revision& end,const svn::Revision&peg,const QString&,bool list_files, int limit,QWidget*parent=0); + virtual bool getSingleLog(svn::LogEntry&,const svn::Revision&,const QString&,const svn::Revision&,QString&root); + + void makeBlame(const svn::Revision&start, const svn::Revision&end, SvnItem*k); + void makeBlame(const svn::Revision&start, const svn::Revision&end, const QString&,QWidget*parent=0,const svn::Revision&peg=svn::Revision::UNDEFINED,SimpleLogCb*_acb=0); + void makeUpdate(const QStringList&what,const svn::Revision&rev,bool recurse); + bool makeSwitch(const QString&rUrl,const QString&tPath,const svn::Revision&r,svn::Depth depth,const svn::Revision&peg,bool stickydepth,bool ignore_externals,bool allow_unversioned); + bool makeSwitch(const QString&path,const QString&what); + bool makeRelocate(const QString&fUrl,const QString&tUrl,const QString&path,bool rec = true); + bool makeCheckout(const QString&,const QString&,const svn::Revision&,const svn::Revision&,svn::Depth,bool isExport,bool openit,bool ignore_externals,bool overwrite,QWidget*p); + void makeInfo(QPtrList<SvnItem> lst,const svn::Revision&,const svn::Revision&,bool recursive = true); + void makeInfo(const QStringList&lst,const svn::Revision&,const svn::Revision&,bool recursive = true); + bool makeCommit(const svn::Targets&); + void CheckoutExport(const QString&what,bool _exp,bool urlisTarget=false); + + QString getInfo(QPtrList<SvnItem> lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all=true); + QString getInfo(const QString&_what,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all=true); + + QString makeMkdir(const QString&); + bool makeMkdir(const QStringList&,const QString&); + bool isLocalWorkingCopy(const KURL&url,QString&_baseUri); + bool createUpdateCache(const QString&what); + bool checkUpdateCache(const QString&path)const; + bool isUpdated(const QString&path)const; + bool getUpdated(const QString&path,svn::SharedPointer<svn::Status>&d)const; + void clearUpdateCache(); + void removeFromUpdateCache(const QStringList&what,bool exact_only); + void stopCheckModThread(); + void stopCheckUpdateThread(); + void startFillCache(const QString&path); + void stopFillCache(); + void stopMain(); + void killallThreads(); + + bool checkUpdatesRunning(); + void getaddedItems(const QString&path,svn::StatusEntries&target); + + bool makeCopy(const QString&,const QString&,const svn::Revision&rev); + bool makeCopy(const KURL::List&,const QString&,const svn::Revision&rev); + + bool makeMove(const QString&,const QString&,bool); + bool makeMove(const KURL::List&,const QString&,bool); + + virtual bool makeCleanup(const QString&); + + bool get(const QString&what,const QString& to,const svn::Revision&rev,const svn::Revision&peg,QWidget*p); + bool singleInfo(const QString&what,const svn::Revision&rev,svn::InfoEntry&target,const svn::Revision&_peg=svn::Revision::UNDEFINED); + + void setContextData(const QString&,const QString&); + void clearContextData(); + QString getContextData(const QString&)const; + + bool threadRunning(ThreadType which); + + virtual void customEvent ( QCustomEvent * e ); + + bool doNetworking(); + +protected: + svn::smart_pointer<SvnActionsData> m_Data; + + void CheckoutExport(bool _exp); + void CheckoutExportCurrent(bool _exp); + void makeAdd(bool rec); + CheckModifiedThread*m_CThread,*m_UThread; + FillCacheThread*m_FCThread; + void makeDiffinternal(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*,const svn::Revision&peg=svn::Revision::UNDEFINED); + void makeDiffExternal(const QString&p1,const svn::Revision&start,const QString&p2,const svn::Revision&end,const svn::Revision&_peg,bool isDir,QWidget*p,bool rec=true); + +public slots: + virtual void dispDiff(const QByteArray&); + virtual void slotProperties(); + virtual void slotNotifyMessage(const QString&); + virtual void slotCommit(); + virtual void slotUpdateHeadRec(); + virtual void slotUpdateTo(); + virtual void slotAdd(); + virtual void slotAddRec(); + virtual void slotCheckoutCurrent(); + virtual void slotExportCurrent(); + virtual void slotCheckout(); + virtual void slotExport(); + virtual void slotRevert(); + virtual void slotRevertItems(const QStringList&); + virtual void slotSwitch(); + virtual void slotResolved(const QString&); + virtual void slotResolve(const QString&); + virtual void makeDiff(const QString&,const svn::Revision&,const svn::Revision&,const svn::Revision&_peg,bool isDir); + virtual void makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&); + virtual void makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,const svn::Revision&,bool,QWidget*p); + virtual void makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + virtual void makeNorecDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + virtual void slotImport(const QString&,const QString&,const QString&,svn::Depth,bool noIgnore,bool noUnknown); + virtual void slotMergeWcRevisions(const QString&,const svn::Revision&,const svn::Revision&,bool,bool,bool,bool); + virtual void slotMerge(const QString&,const QString&, const QString&, + const svn::Revision&,const svn::Revision&,const svn::Revision&, + bool,bool,bool,bool); + virtual void slotMergeExternal(const QString&src1,const QString&src2, const QString&target, + const svn::Revision&rev1,const svn::Revision&rev2,const svn::Revision&_peg,bool); + virtual void slotExtraLogMsg(const QString&); + virtual void slotMakeCat(const svn::Revision&start, const QString&what,const QString&disp,const svn::Revision&peg,QWidget*dlgparent); + + virtual void slotCancel(bool); + +signals: + void clientException(const QString&); + void sendNotify(const QString&); + void reinitItem(SvnItem*); + void sigRefreshAll(); + void sigThreadsChanged(); + void sigRefreshCurrent(SvnItem*); + void sigRefreshIcons(bool); + void sigExtraLogMsg(const QString&); + void sigGotourl(const QString&); + void sigCacheStatus(Q_LONG,Q_LONG); + +protected slots: + virtual void wroteStdin(KProcess*); + virtual void procClosed(KProcess*); + virtual void checkModthread(); + virtual void checkUpdateThread(); + virtual void receivedStderr(KProcess*,char*,int); +}; + +#endif diff --git a/src/svnfrontend/svnfiletip.cpp b/src/svnfrontend/svnfiletip.cpp new file mode 100644 index 0000000..2021169 --- /dev/null +++ b/src/svnfrontend/svnfiletip.cpp @@ -0,0 +1,308 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnfiletip.h" +#include "svnitem.h" + +#include <kfileitem.h> +#include <kglobalsettings.h> +#include <kstandarddirs.h> +#include <kapplication.h> +#include <kdebug.h> + +#include <qlabel.h> +#include <qtooltip.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qscrollview.h> +#include <qtimer.h> + +SvnFileTip::SvnFileTip(QScrollView*parent) + : QFrame( 0, 0, WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM ), + m_on( false ), + m_preview( false ), + m_filter( false ), + m_corner( 0 ), + m_num( 0 ), + m_view( parent ), + m_svnitem( 0 ), + m_previewJob( 0 ) +{ + m_iconLabel = new QLabel(this); + m_textLabel = new QLabel(this); + m_textLabel->setAlignment(Qt::AlignAuto | Qt::AlignTop); + + QGridLayout* layout = new QGridLayout(this, 1, 2, 8, 0); + layout->addWidget(m_iconLabel, 0, 0); + layout->addWidget(m_textLabel, 0, 1); + layout->setResizeMode(QLayout::Fixed); + + setPalette( QToolTip::palette() ); + setMargin( 1 ); + setFrameStyle( QFrame::Plain | QFrame::Box ); + + m_timer = new QTimer(this); + + hide(); +} + + +SvnFileTip::~SvnFileTip() +{ + if ( m_previewJob ) { + m_previewJob->kill(); + m_previewJob = 0; + } +} + +void SvnFileTip::setPreview(bool on) +{ + m_preview = on; + if(on) + m_iconLabel->show(); + else + m_iconLabel->hide(); +} + +void SvnFileTip::setOptions( bool on, bool preview, int num ) +{ + setPreview(preview); + m_on = on; + m_num = num; +} + +void SvnFileTip::setItem(SvnItem*item, const QRect &rect, const QPixmap *pixmap ) +{ + hideTip(); + + if (!m_on) return; + + if ( m_previewJob ) { + m_previewJob->kill(); + m_previewJob = 0; + } + + m_rect = rect; + m_svnitem=item; + + if ( m_svnitem ) { + + if (m_preview) { + if ( pixmap ) + m_iconLabel->setPixmap( *pixmap ); + else + m_iconLabel->setPixmap( QPixmap() ); + } + + // Don't start immediately, because the user could move the mouse over another item + // This avoids a quick sequence of started preview-jobs + m_timer->disconnect( this ); + connect(m_timer, SIGNAL(timeout()), this, SLOT(startDelayed())); + m_timer->start( 300, true ); + } else { + m_timer->stop(); + } +} + +void SvnFileTip::reposition() +{ + if ( m_rect.isEmpty() || !m_view || !m_view->viewport() ) return; + + QRect rect = m_rect; + QPoint off = m_view->viewport()->mapToGlobal( m_view->contentsToViewport( rect.topRight() ) ); + rect.moveTopRight( off ); + + QPoint pos = rect.center(); + // m_corner: + // 0: upperleft + // 1: upperright + // 2: lowerleft + // 3: lowerright + // 4+: none + m_corner = 0; + // should the tooltip be shown to the left or to the right of the ivi ? + QRect desk = KGlobalSettings::desktopGeometry(rect.center()); + if (rect.center().x() + width() > desk.right()) + { + // to the left + if (pos.x() - width() < 0) { + pos.setX(0); + m_corner = 4; + } else { + pos.setX( pos.x() - width() ); + m_corner = 1; + } + } + // should the tooltip be shown above or below the ivi ? + if (rect.bottom() + height() > desk.bottom()) + { + // above + pos.setY( rect.top() - height() ); + m_corner += 2; + } + else pos.setY( rect.bottom() + 1 ); + + move( pos ); + update(); +} + +void SvnFileTip::gotPreview( const KFileItem* item, const QPixmap& pixmap ) +{ + m_previewJob = 0; + if (!m_svnitem || item != m_svnitem->fileItem()) return; + + m_iconLabel -> setPixmap(pixmap); +} + +void SvnFileTip::gotPreviewResult() +{ + m_previewJob = 0; +} + +void SvnFileTip::drawContents( QPainter *p ) +{ + static const char * const names[] = { + "arrow_topleft", + "arrow_topright", + "arrow_bottomleft", + "arrow_bottomright" + }; + + if (m_corner >= 4) { // 4 is empty, so don't draw anything + QFrame::drawContents( p ); + return; + } + + if ( m_corners[m_corner].isNull()) + m_corners[m_corner].load( locate( "data", QString::fromLatin1( "konqueror/pics/%1.png" ).arg( names[m_corner] ) ) ); + + QPixmap &pix = m_corners[m_corner]; + + switch ( m_corner ) + { + case 0: + p->drawPixmap( 3, 3, pix ); + break; + case 1: + p->drawPixmap( width() - pix.width() - 3, 3, pix ); + break; + case 2: + p->drawPixmap( 3, height() - pix.height() - 3, pix ); + break; + case 3: + p->drawPixmap( width() - pix.width() - 3, height() - pix.height() - 3, pix ); + break; + } + + QFrame::drawContents( p ); +} + +void SvnFileTip::setFilter( bool enable ) +{ + if ( enable == m_filter ) return; + + if ( enable ) { + kapp->installEventFilter( this ); + QApplication::setGlobalMouseTracking( true ); + } + else { + QApplication::setGlobalMouseTracking( false ); + kapp->removeEventFilter( this ); + } + m_filter = enable; +} + +void SvnFileTip::showTip() +{ + if (!m_svnitem) { + hide(); + return; + } + QString text = m_svnitem->getToolTipText(); + + if ( text.isEmpty() ) return; + + m_timer->disconnect( this ); + connect(m_timer, SIGNAL(timeout()), this, SLOT(hideTip())); + m_timer->start( 15000, true ); + + m_textLabel->setText( text ); + + setFilter( true ); + + reposition(); + show(); +} + +void SvnFileTip::hideTip() +{ + m_timer->stop(); + setFilter( false ); + if ( isShown() && m_view && m_view->viewport() && + (m_view->horizontalScrollBar()->isShown() || m_view->verticalScrollBar()->isShown()) ) + m_view->viewport()->update(); + hide(); +} +void SvnFileTip::startDelayed() +{ + if (!m_svnitem) { + return; + } + if ( m_preview && m_svnitem->fileItem() ) { + KFileItemList oneItem; + oneItem.append( m_svnitem->fileItem() ); + + m_previewJob = KIO::filePreview( oneItem, 256, 256, 64, 70, true, true, 0); + connect( m_previewJob, SIGNAL( gotPreview( const KFileItem *, const QPixmap & ) ), + this, SLOT( gotPreview( const KFileItem *, const QPixmap & ) ) ); + connect( m_previewJob, SIGNAL( result( KIO::Job * ) ), + this, SLOT( gotPreviewResult() ) ); + } + + m_timer->disconnect( this ); + connect(m_timer, SIGNAL(timeout()), this, SLOT(showTip())); + m_timer->start( 400, true ); +} + +void SvnFileTip::resizeEvent( QResizeEvent* event ) +{ + QFrame::resizeEvent(event); + reposition(); +} + +bool SvnFileTip::eventFilter( QObject *, QEvent *e ) +{ + switch ( e->type() ) + { + case QEvent::Leave: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Wheel: + hideTip(); + default: break; + } + + return false; +} + +#include "svnfiletip.moc" diff --git a/src/svnfrontend/svnfiletip.h b/src/svnfrontend/svnfiletip.h new file mode 100644 index 0000000..d63cf97 --- /dev/null +++ b/src/svnfrontend/svnfiletip.h @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + /* this is mostly a copy of KonqFileTip + * when kdesvn get part of KDE itself it should replaced then with the original stuff + * now we make sure we may us it + */ + +#ifndef SVNFILETIP_H +#define SVNFILETIP_H +#include <qframe.h> +#include <qpixmap.h> +#include <kio/previewjob.h> + +class KFileItem; +class QLabel; +class QScrollView; +class QTimer; +class SvnItem; + +/** +@author Rajko Albrecht +*/ +class SvnFileTip : public QFrame +{ +Q_OBJECT +public: + SvnFileTip(QScrollView*parent); + virtual ~SvnFileTip(); + void setPreview(bool on); + + /** + @param on show tooltip at all + @param preview include file preview in tooltip + @param num the number of tooltip texts to get from KFileItem + */ + void setOptions( bool on, bool preview, int num ); + + /** Set the item from which to get the tip information + @param item the item from which to get the tip information + @param rect the rectangle around which the tip will be shown + @param pixmap the pixmap to be shown. If 0, no pixmap is shown + */ + void setItem(SvnItem*item, const QRect &rect = QRect(), + const QPixmap *pixmap = 0 ); + + virtual bool eventFilter( QObject *, QEvent *e ); + + protected: + virtual void drawContents( QPainter *p ); + virtual void resizeEvent( QResizeEvent * ); + + private slots: + void gotPreview( const KFileItem*, const QPixmap& ); + void gotPreviewResult(); + + void startDelayed(); + void showTip(); + void hideTip(); + + private: + void setFilter( bool enable ); + + void reposition(); + + QLabel* m_iconLabel; + QLabel* m_textLabel; + bool m_on : 1; + bool m_preview : 1; // shall the preview icon be shown + bool m_filter : 1; + QPixmap m_corners[4]; + int m_corner; + int m_num; + QScrollView* m_view; + SvnItem* m_svnitem; + KIO::PreviewJob* m_previewJob; + QRect m_rect; + QTimer* m_timer; +}; + +#endif diff --git a/src/svnfrontend/svnitem.cpp b/src/svnfrontend/svnitem.cpp new file mode 100644 index 0000000..20133d5 --- /dev/null +++ b/src/svnfrontend/svnitem.cpp @@ -0,0 +1,535 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "svnitem.h" +#include "svnactions.h" +#include "kdesvn_part.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/status.hpp" +#include "src/svnqt/smart_pointer.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/sub2qt.h" +#include "helpers/ktranslateurl.h" + +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <kiconeffect.h> +#include <kfileitem.h> +#include <kdebug.h> + +#include <qstring.h> +#include <qfileinfo.h> +#include <qimage.h> +#include <qptrlist.h> +#include <qpainter.h> +#include <qbitmap.h> + +class SvnItem_p:public svn::ref_count +{ + friend class SvnItem; +public: + SvnItem_p(); + SvnItem_p(const svn::StatusPtr&); + virtual ~SvnItem_p(); + KFileItem*createItem(const svn::Revision&peg); + const KURL& kdeName(const svn::Revision&); + KMimeType::Ptr mimeType(bool dir=false); + +protected: + svn::StatusPtr m_Stat; + void init(); + QString m_url,m_full,m_short; + KURL m_kdename; + QDateTime m_fullDate; + QString m_infoText; + KFileItem*m_fitem; + bool isWc; + svn::Revision lRev; + KMimeType::Ptr mptr; +}; + +SvnItem_p::SvnItem_p() + :ref_count(),m_Stat(new svn::Status()) +{ + init(); +} + +SvnItem_p::SvnItem_p(const svn::StatusPtr&aStat) + :ref_count(),m_Stat(aStat) +{ + init(); +} + +SvnItem_p::~SvnItem_p() +{ + delete m_fitem; +} + +void SvnItem_p::init() +{ + m_full = m_Stat->path(); + m_kdename=""; + mptr = 0; + lRev=svn::Revision::UNDEFINED; + while (m_full.endsWith("/")) { + /* dir name possible */ + m_full.truncate(m_full.length()-1); + } + int p = m_full.findRev("/"); + if (p>-1) { + ++p; + m_short = m_full.right(m_full.length()-p); + } else { + m_short = m_full; + } + m_url = m_Stat->entry().url(); + m_fullDate = svn::DateTime(m_Stat->entry().cmtDate()); + m_infoText = QString::null; + m_fitem = 0; +} + +KMimeType::Ptr SvnItem_p::mimeType(bool dir) +{ + if (!mptr||m_kdename.isEmpty()) { + if (m_kdename.isEmpty()) { + kdeName(svn::Revision::UNDEFINED); + } + if (dir) { + mptr = KMimeType::mimeType("inode/directory"); + } else { + mptr = KMimeType::findByURL(m_kdename,0,isWc,!isWc); + } + } + return mptr; +} + +const KURL& SvnItem_p::kdeName(const svn::Revision&r) +{ + isWc = !svn::Url::isValid(m_Stat->path()); + QString name; + if (!(r==lRev)||m_kdename.isEmpty()) { + lRev=r; + if (!isWc) { + m_kdename = m_Stat->entry().url(); + QString proto; + proto = helpers::KTranslateUrl::makeKdeUrl(m_kdename.protocol()); + m_kdename.setProtocol(proto); + QString revstr= lRev.toString(); + if (revstr.length()>0) { + m_kdename.setQuery("?rev="+revstr); + } + } else { + m_kdename = KURL::fromPathOrURL(m_Stat->path()); + } + } + return m_kdename; +} + +KFileItem*SvnItem_p::createItem(const svn::Revision&peg) +{ + if (!m_fitem||!(peg==lRev) ) { + delete m_fitem; + m_fitem=0; + m_fitem=new KFileItem(KFileItem::Unknown,KFileItem::Unknown,kdeName(peg)); + } + return m_fitem; +} + +SvnItem::SvnItem() + : p_Item(new SvnItem_p()) +{ + m_overlaycolor = false; +} + +SvnItem::SvnItem(const svn::StatusPtr&aStat) + : p_Item(new SvnItem_p(aStat)) +{ + m_overlaycolor = false; +} + +SvnItem::~SvnItem() +{ +} + +void SvnItem::setStat(const svn::StatusPtr&aStat) +{ + m_overlaycolor = false; + p_Item = new SvnItem_p(aStat); +} + +const QString&SvnItem::fullName()const +{ + return (p_Item->m_full); +} + +const QString&SvnItem::shortName()const +{ + return (p_Item->m_short); +} + +const QString&SvnItem::Url()const +{ + return (p_Item->m_url); +} + +bool SvnItem::isDir()const +{ + if (isRemoteAdded() || p_Item->m_Stat->entry().isValid()) { + return p_Item->m_Stat->entry().kind()==svn_node_dir; + } + /* must be a local file */ + QFileInfo f(fullName()); + return f.isDir(); +} + +const QDateTime&SvnItem::fullDate()const +{ + return (p_Item->m_fullDate); +} + +QPixmap SvnItem::internalTransform(const QPixmap&first,int size) +{ + QPixmap result(size,size); + if (result.isNull()) { + return result; + } + const QBitmap * b = first.mask(); + result.fill(Qt::white); + if (b) { + result.setMask(*b); + } else { + QBitmap m(size,size,true); + m.fill(Qt::white); + result.setMask(m); + } + QPainter pa; + pa.begin(&result); + int w = first.width()>size?size:first.width(); + int h = first.height()>size?size:first.height(); + pa.drawPixmap(0,0,first,0,0,w,h); + pa.end(); + return result; +} + +QPixmap SvnItem::getPixmap(const QPixmap&_p,int size,bool overlay) +{ + if (!isVersioned()) { + m_bgColor = NOTVERSIONED; + } else if (isRealVersioned()) { + SvnActions*wrap = getWrapper(); + bool mod = false; + QPixmap p2 = QPixmap(); + if (p_Item->m_Stat->textStatus()==svn_wc_status_conflicted) { + m_bgColor = CONFLICT; + if (overlay) + p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnconflicted",KIcon::Desktop,size); + } else if (p_Item->m_Stat->textStatus ()==svn_wc_status_missing) { + m_bgColor = MISSING; + } else if (isLocked()||wrap->checkReposLockCache(fullName())) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnlocked",KIcon::Desktop,size); + m_bgColor = LOCKED; + } else if (Kdesvnsettings::check_needslock() && !isRemoteAdded() && wrap->isLockNeeded(this,svn::Revision::UNDEFINED) ) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnneedlock",KIcon::Desktop,size); + m_bgColor = NEEDLOCK; + } else if (wrap->isUpdated(p_Item->m_Stat->path())) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnupdates",KIcon::Desktop,size); + m_bgColor = UPDATES; + } else if (p_Item->m_Stat->textStatus()==svn_wc_status_deleted) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvndeleted",KIcon::Desktop,size); + m_bgColor = DELETED; + } else if (p_Item->m_Stat->textStatus()==svn_wc_status_added ) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnadded",KIcon::Desktop,size); + m_bgColor = ADDED; + } else if (isModified()) { + mod = true; + } else if (isDir()&&wrap) { + svn::StatusEntries dlist; + svn::StatusEntries::const_iterator it; + if (isRemoteAdded() || wrap->checkUpdateCache(fullName())) { + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnupdates",KIcon::Desktop,size); + m_bgColor = UPDATES; + } else if (wrap->checkConflictedCache(fullName())) { + m_bgColor = CONFLICT; + if (overlay) + p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnconflicted",KIcon::Desktop,size); + } else { + mod = wrap->checkModifiedCache(fullName()); + } + } + if (mod) { + m_bgColor = MODIFIED; + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnmodified",KIcon::Desktop,size); + } + if (!p2.isNull()) { + QPixmap p; + if (_p.width()!=size || _p.height()!=size) { + p = internalTransform(_p,size); + } else { + p = _p; + } + m_overlaycolor = true; + QImage i1; i1 = p; + QImage i2;i2 = p2; + + KIconEffect::overlay(i1,i2); + p = i1; + return p; + } + } + return _p; +} + +QPixmap SvnItem::getPixmap(int size,bool overlay) +{ + QPixmap p; + m_overlaycolor = false; + m_bgColor = NONE; + /* yes - different way to "isDir" above 'cause here we try to use the + mime-features of KDE on ALL not just unversioned entries. + */ + if (svn::Url::isValid(p_Item->m_Stat->path())) { + /* remote access */ + p = p_Item->mimeType(isDir())->pixmap(KIcon::Desktop,size,KIcon::DefaultState); + if (isLocked()) { + m_bgColor = LOCKED; + QPixmap p2; + if (overlay) p2 = kdesvnPartFactory::instance()->iconLoader()->loadIcon("kdesvnlocked",KIcon::Desktop,size); + if (!p2.isNull()) { + QImage i1; i1 = p; + QImage i2; i2 = p2; + KIconEffect::overlay(i1,i2); + p = i1; + } + } + } else { + if (isRemoteAdded()) { + if (isDir()) { + p = kdesvnPartFactory::instance()->iconLoader()->loadIcon("folder",KIcon::Desktop,size); + } else { + p = kdesvnPartFactory::instance()->iconLoader()->loadIcon("unknown",KIcon::Desktop,size); + } + } else { + KURL uri; + uri.setPath(fullName()); + p = KMimeType::pixmapForURL(uri,0,KIcon::Desktop,size); + p = getPixmap(p,size,overlay); + } + } + return p; +} + +bool SvnItem::isVersioned()const +{ + return p_Item->m_Stat->isVersioned(); +} + +bool SvnItem::isValid()const +{ + if (isVersioned()) { + return true; + } + QFileInfo f(fullName()); + return f.exists(); +} + +bool SvnItem::isRealVersioned()const +{ + return p_Item->m_Stat->isRealVersioned(); +} + +bool SvnItem::isIgnored()const +{ + return p_Item->m_Stat->textStatus()==svn_wc_status_ignored; +} + +bool SvnItem::isRemoteAdded()const +{ + return getWrapper()->isUpdated(p_Item->m_Stat->path()) && + p_Item->m_Stat->validReposStatus()&&!p_Item->m_Stat->validLocalStatus(); +} + +QString SvnItem::infoText()const +{ + QString info_text = ""; + if (getWrapper()->isUpdated(p_Item->m_Stat->path())) { + if (p_Item->m_Stat->validReposStatus()&&!p_Item->m_Stat->validLocalStatus()) { + info_text = i18n("Added in repository"); + } else { + info_text = i18n("Needs update"); + } + } else { + switch(p_Item->m_Stat->textStatus ()) { + case svn_wc_status_modified: + info_text = i18n("Locally modified"); + break; + case svn_wc_status_added: + info_text = i18n("Locally added"); + break; + case svn_wc_status_missing: + info_text = i18n("Missing"); + break; + case svn_wc_status_deleted: + info_text = i18n("Deleted"); + break; + case svn_wc_status_replaced: + info_text = i18n("Replaced"); + break; + case svn_wc_status_ignored: + info_text = i18n("Ignored"); + break; + case svn_wc_status_external: + info_text=i18n("External"); + break; + case svn_wc_status_conflicted: + info_text=i18n("Conflict"); + break; + case svn_wc_status_merged: + info_text=i18n("Merged"); + break; + case svn_wc_status_incomplete: + info_text=i18n("Incomplete"); + break; + default: + break; + } + if (info_text.isEmpty()) { + switch (p_Item->m_Stat->propStatus ()) { + case svn_wc_status_modified: + info_text = i18n("Property modified"); + break; + default: + break; + } + } + } + return info_text; +} + +QString SvnItem::cmtAuthor()const +{ + return p_Item->m_Stat->entry().cmtAuthor(); +} + +long int SvnItem::cmtRev()const +{ + return p_Item->m_Stat->entry().cmtRev(); +} + +bool SvnItem::isLocked()const +{ + return p_Item->m_Stat->entry().lockEntry().Locked(); +} + +QString SvnItem::lockOwner()const +{ + if (p_Item->m_Stat->entry().lockEntry().Locked()) { + return p_Item->m_Stat->entry().lockEntry().Owner(); + } + svn::SharedPointer<svn::Status> tmp; + if (getWrapper()->checkReposLockCache(fullName(),tmp) && tmp) { + return tmp->lockEntry().Owner(); + } + return ""; +} + + +/*! + \fn SvnItem::isModified() + */ +bool SvnItem::isModified()const +{ + return p_Item->m_Stat->textStatus ()==svn_wc_status_modified||p_Item->m_Stat->propStatus()==svn_wc_status_modified + ||p_Item->m_Stat->textStatus ()==svn_wc_status_replaced; +} + +const svn::StatusPtr& SvnItem::stat()const +{ + return p_Item->m_Stat; +} + + +/*! + \fn SvnItem::isNormal()const + */ +bool SvnItem::isNormal()const +{ + return p_Item->m_Stat->textStatus()==svn_wc_status_normal; +} + +bool SvnItem::isMissing()const +{ + return p_Item->m_Stat->textStatus()==svn_wc_status_missing; +} + +bool SvnItem::isDeleted()const +{ + return p_Item->m_Stat->textStatus()==svn_wc_status_deleted; +} + +bool SvnItem::isConflicted()const +{ + return p_Item->m_Stat->textStatus()==svn_wc_status_conflicted; +} + +/*! + \fn SvnItem::getToolTipText() + */ +const QString& SvnItem::getToolTipText() +{ + if (p_Item->m_infoText.isNull()) { + if (isRealVersioned() && !p_Item->m_Stat->entry().url().isEmpty()) { + SvnActions*wrap = getWrapper(); + svn::Revision peg(svn_opt_revision_unspecified); + svn::Revision rev(svn_opt_revision_unspecified); + if (svn::Url::isValid(p_Item->m_Stat->path())) { + /* remote */ + rev = p_Item->m_Stat->entry().revision(); + peg = correctPeg(); + } else { + /* local */ + } + if (wrap) { + QPtrList<SvnItem> lst; lst.append(this); + p_Item->m_infoText = wrap->getInfo(lst,rev,peg,false,false); + if (p_Item->m_fitem) p_Item->m_infoText+=p_Item->m_fitem->getToolTipText(0); + } + } else if (p_Item->m_fitem){ + p_Item->m_infoText=p_Item->m_fitem->getToolTipText(6); + } + } + return p_Item->m_infoText; +} + +KFileItem*SvnItem::fileItem() +{ + return p_Item->createItem(correctPeg()); +} + +const KURL&SvnItem::kdeName(const svn::Revision&r) +{ + return p_Item->kdeName(r); +} + +KMimeType::Ptr SvnItem::mimeType() +{ + return p_Item->mimeType(isDir()); +} diff --git a/src/svnfrontend/svnitem.h b/src/svnfrontend/svnitem.h new file mode 100644 index 0000000..ac90172 --- /dev/null +++ b/src/svnfrontend/svnitem.h @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef __SVN_ITEM_H +#define __SVN_ITEM_H + +#include "src/svnqt/smart_pointer.hpp" +#include "src/svnqt/svnqttypes.hpp" +#include <kmimetype.h> +#include <qstring.h> +#include <qdatetime.h> +#include <qpixmap.h> +#include <qptrlist.h> + +class FileListViewItem; +class SvnItem_p; +class SvnActions; +class KFileItem; +class KURL; + +namespace svn +{ + class Revision; +} + +class SvnItem +{ +public: + SvnItem(); + SvnItem(const svn::StatusPtr&); + virtual ~SvnItem(); + + virtual const QString&fullName()const; + virtual const QString&shortName()const; + virtual const QString&Url()const; + virtual const KURL&kdeName(const svn::Revision&); + virtual KMimeType::Ptr mimeType(); + virtual const QDateTime&fullDate()const; + virtual bool isDir()const; + virtual bool isVersioned()const; + virtual bool isConflicted()const; + virtual bool isValid()const; + virtual bool isRealVersioned()const; + virtual bool isIgnored()const; + virtual bool isRemoteAdded()const; + virtual QString infoText()const; + virtual QString cmtAuthor()const; + virtual long int cmtRev()const; + virtual bool isLocked()const; + virtual QString lockOwner()const; + virtual QString getParentDir()const=0; + virtual SvnItem* getParentItem()const=0; + virtual const svn::Revision&correctPeg()const=0; + virtual void refreshStatus(bool childs=false,QPtrList<SvnItem> *exclude = 0,bool depsonly=false)=0; + + QPixmap getPixmap(int size,bool overlay=true); + QPixmap getPixmap(const QPixmap&,int size,bool overlay=true); + + virtual FileListViewItem*fItem(){return 0;} + virtual void setStat(const svn::StatusPtr&); + virtual const svn::StatusPtr& stat()const; + virtual bool isModified()const; + bool isNormal()const; + bool isMissing()const; + bool isDeleted()const; + const QString& getToolTipText(); + KFileItem*fileItem(); + +protected: + bool m_overlaycolor; + enum color_type { + NONE = 0, + UPDATES = 1, + MODIFIED = 2, + LOCKED = 3, + ADDED = 4, + DELETED = 5, + MISSING = 6, + NOTVERSIONED = 7, + CONFLICT = 8, + NEEDLOCK = 9 + }; + color_type m_bgColor; + svn::smart_pointer<SvnItem_p> p_Item; + virtual SvnActions*getWrapper()const = 0; + + static QPixmap internalTransform(const QPixmap&,int size); + +}; + +typedef QPtrList<SvnItem> SvnItemList; +typedef QPtrListIterator<SvnItem> SvnItemListIterator; + +#endif diff --git a/src/svnfrontend/svnlogdlg.ui b/src/svnfrontend/svnlogdlg.ui new file mode 100644 index 0000000..85038e2 --- /dev/null +++ b/src/svnfrontend/svnlogdlg.ui @@ -0,0 +1,479 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>SvnLogDialogData</class> +<widget class="QDialog"> + <property name="name"> + <cstring>LogDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>485</width> + <height>345</height> + </rect> + </property> + <property name="caption"> + <string>SVN Log</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton" row="1" column="2"> + <property name="name"> + <cstring>m_goButton</cstring> + </property> + <property name="text"> + <string>Get Logs</string> + </property> + </widget> + <widget class="RevisionButtonImpl" row="1" column="1"> + <property name="name"> + <cstring>m_endRevButton</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>endLabel</cstring> + </property> + <property name="text"> + <string>End revision</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>startLabel</cstring> + </property> + <property name="text"> + <string>Start revision</string> + </property> + </widget> + <widget class="RevisionButtonImpl" row="1" column="0"> + <property name="name"> + <cstring>m_startRevButton</cstring> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>107</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QSplitter"> + <property name="name"> + <cstring>m_centralSplitter</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <widget class="KListView"> + <column> + <property name="text"> + <string>1</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Author</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Revison</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Date</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Message</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_LogView</cstring> + </property> + <property name="vScrollBarMode"> + <enum>Auto</enum> + </property> + <property name="hScrollBarMode"> + <enum>Auto</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="showSortIndicator"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + <property name="fullWidth"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Select in first column revisions for diff</string> + </property> + </widget> + <widget class="QSplitter"> + <property name="name"> + <cstring>m_rightSplitter</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <widget class="KTextBrowser"> + <property name="name"> + <cstring>m_LogDisplay</cstring> + </property> + </widget> + <widget class="KListView"> + <column> + <property name="text"> + <string>Action</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Item</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Copy from</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_ChangedList</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Contextmenu on item for more operations</string> + </property> + </widget> + </widget> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_DispPrevButton</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Diff previous</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_DispSpecDiff</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Diff revisions</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Select second revision with right mouse button</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonListFiles</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>List entries</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonBlame</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Annotate</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>42</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonClose</cstring> + </property> + <property name="text"> + <string>Close</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>RevisionButtonImpl</class> + <header location="local">revisionbuttonimpl.h</header> + <sizehint> + <width>60</width> + <height>20</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <signal>revisionChanged()</signal> + <slot access="public" specifier="">askRevision()</slot> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>buttonClose</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>m_DispPrevButton</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>slotDispPrevious()</slot> + </connection> + <connection> + <sender>m_LogView</sender> + <signal>selectionChanged(QListViewItem*)</signal> + <receiver>LogDialog</receiver> + <slot>slotSelectionChanged(QListViewItem*)</slot> + </connection> + <connection> + <sender>m_LogView</sender> + <signal>mouseButtonClicked(int,QListViewItem*,const QPoint&,int)</signal> + <receiver>LogDialog</receiver> + <slot>slotItemClicked(int,QListViewItem*,const QPoint&,int)</slot> + </connection> + <connection> + <sender>m_DispSpecDiff</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>slotDispSelected()</slot> + </connection> + <connection> + <sender>buttonListFiles</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>slotListEntries()</slot> + </connection> + <connection> + <sender>buttonBlame</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>slotBlameItem()</slot> + </connection> + <connection> + <sender>m_ChangedList</sender> + <signal>selectionChanged()</signal> + <receiver>LogDialog</receiver> + <slot>slotEntriesSelectionChanged()</slot> + </connection> + <connection> + <sender>m_ChangedList</sender> + <signal>contextMenuRequested(QListViewItem*,const QPoint&,int)</signal> + <receiver>LogDialog</receiver> + <slot>slotSingleContext(QListViewItem*,const QPoint&,int)</slot> + </connection> + <connection> + <sender>m_ChangedList</sender> + <signal>doubleClicked(QListViewItem*)</signal> + <receiver>LogDialog</receiver> + <slot>slotSingleDoubleClicked(QListViewItem*)</slot> + </connection> + <connection> + <sender>m_startRevButton</sender> + <signal>revisionChanged()</signal> + <receiver>LogDialog</receiver> + <slot>slotRevisionSelected()</slot> + </connection> + <connection> + <sender>m_endRevButton</sender> + <signal>revisionChanged()</signal> + <receiver>LogDialog</receiver> + <slot>slotRevisionSelected()</slot> + </connection> + <connection> + <sender>m_goButton</sender> + <signal>clicked()</signal> + <receiver>LogDialog</receiver> + <slot>slotGetLogs()</slot> + </connection> +</connections> +<slots> + <slot access="protected">slotSelectionChanged(QListViewItem*)</slot> + <slot access="protected">slotItemChanged(QListViewItem*)</slot> + <slot access="protected">slotDispPrevious()</slot> + <slot access="protected">slotItemClicked(int,QListViewItem*,const QPoint &,int)</slot> + <slot access="protected">slotDispSelected()</slot> + <slot access="protected">slotListEntries()</slot> + <slot access="protected">slotBlameItem()</slot> + <slot access="protected">slotEntriesSelectionChanged()</slot> + <slot access="protected">slotSingleContext(QListViewItem*, const QPoint &, int)</slot> + <slot access="protected">slotSingleDoubleClicked(QListViewItem*)</slot> + <slot access="protected">slotRevisionSelected()</slot> + <slot access="protected">slotGetLogs()</slot> +</slots> +<layoutdefaults spacing="2" margin="2"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>revisionbuttonimpl.h</includehint> + <includehint>revisionbuttonimpl.h</includehint> + <includehint>klistview.h</includehint> + <includehint>ktextbrowser.h</includehint> + <includehint>klistview.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/svnfrontend/svnlogdlgimp.cpp b/src/svnfrontend/svnlogdlgimp.cpp new file mode 100644 index 0000000..9919ab7 --- /dev/null +++ b/src/svnfrontend/svnlogdlgimp.cpp @@ -0,0 +1,661 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnlogdlgimp.h" +#include "src/settings/kdesvnsettings.h" +#include "src/svnqt/log_entry.hpp" +#include "helpers/sub2qt.h" +#include "svnactions.h" +#include "src/svnfrontend/fronthelpers/revisionbuttonimpl.h" + +#include <klistview.h> +#include <ktextbrowser.h> +#include <kpushbutton.h> +#include <kglobal.h> +#include <klocale.h> +#include <kapp.h> +#include <kconfigbase.h> +#include <kconfig.h> +#include <ktabwidget.h> +#include <kdebug.h> + +#include <qdatetime.h> +#include <qheader.h> +#include <qsplitter.h> +#include <qtextstream.h> +#include <qpopupmenu.h> + +#include <list> + + +const char* SvnLogDlgImp::groupName = "log_dialog_size"; + +class LogListViewItem:public KListViewItem +{ +public: + LogListViewItem (KListView *parent,const svn::LogEntry&); + virtual int compare( QListViewItem* i, int col, bool ascending ) const; + + static const int COL_MARKER,COL_REV,COL_AUTHOR,COL_DATE,COL_MSG; + const QString&message()const; + svn_revnum_t rev()const{return _revision;} + void showChangedEntries(KListView*); + unsigned int numChangedEntries(){return changedPaths.count();} + void setChangedEntries(const svn::LogEntry&); + void setRealName(const QString&_n){_realName=_n;} + const QString&realName()const{return _realName;} + + bool copiedFrom(QString&_n,long&rev)const; + static bool isParent(const QString&_par,const QString&tar); + +protected: + svn_revnum_t _revision; + QDateTime fullDate; + QString _message,_realName; + QValueList<svn::LogChangePathEntry> changedPaths; +}; + +const int LogListViewItem::COL_MARKER = 0; +const int LogListViewItem::COL_REV = 2; +const int LogListViewItem::COL_AUTHOR = 1; +const int LogListViewItem::COL_DATE = 3; +const int LogListViewItem::COL_MSG = 4; + +class LogChangePathItem:public KListViewItem +{ +public: + LogChangePathItem(KListView*parent,const svn::LogChangePathEntry&); + virtual ~LogChangePathItem(){} + + QChar action() const{return _action;} + const QString& path() const{return _path;} + const QString& source() const{return _source;} + svn_revnum_t revision() const{ return _revision;} + +protected: + QString _path,_source; + QChar _action; + svn_revnum_t _revision; +}; + +LogListViewItem::LogListViewItem(KListView*_parent,const svn::LogEntry&_entry) + : KListViewItem(_parent),_realName(QString::null) +{ + setMultiLinesEnabled(false); + _revision=_entry.revision; + fullDate=svn::DateTime(_entry.date); + setText(COL_REV,QString("%1").arg(_revision)); + setText(COL_AUTHOR,_entry.author); + setText(COL_DATE,helpers::sub2qt::apr_time2qtString(_entry.date)); + _message = _entry.message; + QStringList sp = QStringList::split("\n",_message); + if (sp.count()==0) { + setText(COL_MSG,_message); + } else { + setText(COL_MSG,sp[0]); + } + changedPaths = _entry.changedPaths; + //setText(COL_MSG,_entry.message.c_str()); +} + +const QString&LogListViewItem::message()const +{ + return _message; +} + +int LogListViewItem::compare( QListViewItem* item, int col, bool ) const +{ + LogListViewItem* k = static_cast<LogListViewItem*>( item ); + if (col==COL_REV) { + return _revision-k->_revision; + } + if (col==COL_DATE) { + return k->fullDate.secsTo(fullDate); + } + return text(col).localeAwareCompare(k->text(col)); +} + +void LogListViewItem::showChangedEntries(KListView*where) +{ + if (!where)return; + where->clear(); + if (changedPaths.count()==0) { + return; + } + for (unsigned i = 0; i < changedPaths.count();++i) { + new LogChangePathItem(where,changedPaths[i]); + } +} + +LogChangePathItem::LogChangePathItem(KListView*parent,const svn::LogChangePathEntry&e) + :KListViewItem(parent) +{ + _action = QChar(e.action); + setText(0,_action); + _path = e.path; + setText(1,e.path); + _revision = e.copyFromRevision; + _source = e.copyFromPath; + if (e.copyFromRevision>-1) + { + setText(2,i18n("%1 at revision %2").arg(e.copyFromPath).arg(e.copyFromRevision)); + } +} + +void LogListViewItem::setChangedEntries(const svn::LogEntry&_entry) +{ + changedPaths = _entry.changedPaths; +} + +bool LogListViewItem::copiedFrom(QString&_n,long&_rev)const +{ + for (unsigned i = 0; i < changedPaths.count();++i) { + if (changedPaths[i].action=='A' && + !changedPaths[i].copyFromPath.isEmpty() && + isParent(changedPaths[i].path,_realName)) { + kdDebug()<<_realName<< " - " << changedPaths[i].path << endl; + QString tmpPath = _realName; + QString r = _realName.mid(changedPaths[i].path.length()); + _n=changedPaths[i].copyFromPath; + _n+=r; + _rev = changedPaths[i].copyFromRevision; + kdDebug()<<"Found switch from "<< changedPaths[i].copyFromPath << " rev "<<changedPaths[i].copyFromRevision<<endl; + kdDebug()<<"Found switch from "<< _n << " rev "<<_rev<<endl; + return true; + } + } + return false; +} + +bool LogListViewItem::isParent(const QString&_par,const QString&tar) +{ + if (_par==tar) return true; + QString par = _par+(_par.endsWith("/")?"":"/"); + return tar.startsWith(par); +} + +SvnLogDlgImp::SvnLogDlgImp(SvnActions*ac,QWidget *parent, const char *name,bool modal) + :SvnLogDialogData(parent, name,modal),_name("") +{ + m_LogView->setSorting(LogListViewItem::COL_REV); + m_LogView->setSortOrder(Qt::Descending); + resize(dialogSize()); + m_ControlKeyDown = false; + m_first = 0; + m_second = 0; + + if (Kdesvnsettings::self()->log_always_list_changed_files()) { + buttonListFiles->hide(); + } else { + m_ChangedList->hide(); + } + m_Actions = ac; + KConfigGroup cs(Kdesvnsettings::self()->config(), groupName); + QString t1 = cs.readEntry("logsplitter",QString::null); + if (!t1.isEmpty()) { + QTextStream st2(&t1,IO_ReadOnly); + st2 >> *m_centralSplitter; + } + t1 = cs.readEntry("right_logsplitter",QString::null); + if (!t1.isEmpty()) { + if (cs.readBoolEntry("laststate",false)==m_ChangedList->isHidden()) { + QTextStream st2(&t1,IO_ReadOnly); + st2 >> *m_rightSplitter; + } + } +} + +SvnLogDlgImp::~SvnLogDlgImp() +{ + QString t1,t2; + QTextStream st1(&t1,IO_WriteOnly); + st1 << *m_rightSplitter; + QTextStream st2(&t2,IO_WriteOnly); + st2 << *m_centralSplitter; + KConfigGroup cs(Kdesvnsettings::self()->config(), groupName); + cs.writeEntry("right_logsplitter",t1); + cs.writeEntry("logsplitter",t2); + cs.writeEntry("laststate",m_ChangedList->isHidden()); +} + +void SvnLogDlgImp::dispLog(const svn::SharedPointer<svn::LogEntriesMap>&_log,const QString & what,const QString&root,const svn::Revision&peg,const QString&pegUrl) +{ + m_peg = peg; + m_PegUrl = pegUrl; + m_first = m_second = 0; + m_startRevButton->setNoWorking(m_PegUrl.isUrl()); + m_endRevButton->setNoWorking(m_PegUrl.isUrl()); + if (!m_PegUrl.isUrl() || Kdesvnsettings::remote_special_properties()) { + QString s = m_Actions->searchProperty(_bugurl,"bugtraq:url",pegUrl,peg,true); + if (!s.isEmpty() ){ + QString reg; + s = m_Actions->searchProperty(reg,"bugtraq:logregex",pegUrl,peg,true); + if (!s.isNull() && !reg.isEmpty()) { + QStringList s1 = QStringList::split("\n",reg); + if (s1.size()>0) { + _r1.setPattern(s1[0]); + if (s1.size()>1) { + _r2.setPattern(s1[1]); + } + } + } + } + } + _base = root; + m_first = m_second = 0; + m_Entries = _log; + kdDebug()<<"What: "<<what << endl; + if (!what.isEmpty()){ + setCaption(i18n("SVN Log of %1").arg(what)); + } else { + setCaption(i18n("SVN Log")); + } + _name = what; + dispLog(_log); +} + +void SvnLogDlgImp::dispLog(const svn::SharedPointer<svn::LogEntriesMap>&_log) +{ + m_LogView->clear(); + m_LogView->header()->setLabel(0, " "); + m_LogView->setColumnWidth(0,10); + if (!_log) { + return; + } + svn::LogEntriesMap::const_iterator lit; + LogListViewItem * item; + QMap<long int,QString> namesMap; + QMap<long int,LogListViewItem*> itemMap; + long min,max; + min = max = -1; + for (lit=_log->begin();lit!=_log->end();++lit) { + item = new LogListViewItem(m_LogView,(*lit)); + if ((*lit).revision>max) max = (*lit).revision; + if ((*lit).revision<min || min == -1) min = (*lit).revision; + itemMap[(*lit).revision]=item; + } + if (itemMap.count()==0) { + return; + } + m_startRevButton->setRevision(max); + m_endRevButton->setRevision(min); + m_LogView->setSelected(m_LogView->firstChild(),true); + QString bef = _name; + long rev; + // YES! I'd checked it: this is much faster than getting list of keys + // and iterating over that list! + for (long c=max;c>-1;--c) { + if (!itemMap.contains(c)) { + continue; + } + if (itemMap[c]->realName().isEmpty()) { + itemMap[c]->setRealName(bef); + } + itemMap[c]->copiedFrom(bef,rev); + } +} + +QString SvnLogDlgImp::genReplace(const QString&r1match) +{ + static QString anf("<a href=\""); + static QString mid("\">"); + static QString end("</a>"); + QString res(""); + if (_r2.pattern().length()<1) { + res = _bugurl; + res.replace("%BUGID%",_r1.cap(1)); + res = anf+res+mid+r1match+end; + return res; + } + int pos=0; + int count=0; + int oldpos; + + kdDebug()<<"Search second pattern: "<<_r2.pattern()<<" in "<<r1match<<endl; + + while (pos > -1) { + oldpos = pos+count; + pos = r1match.find(_r2,pos+count); + if (pos==-1) { + break; + } + count = _r2.matchedLength(); + res+=r1match.mid(oldpos,pos-oldpos); + QString sub = r1match.mid(pos,count); + QString _url = _bugurl; + _url.replace("%BUGID%",sub); + res+=anf+_url+mid+sub+end; + } + res+=r1match.mid(oldpos); + return res; +} + +void SvnLogDlgImp::replaceBugids(QString&msg) +{ + msg = QStyleSheet::convertFromPlainText(msg); + if (!_r1.isValid() || _r1.pattern().length()<1 || _bugurl.isEmpty()) { + return; + } + kdDebug()<<"Try match "<< _r1.pattern() << endl; + int pos = 0; + int count = 0; + + pos = _r1.search(msg,pos+count); + count = _r1.matchedLength(); + + while (pos>-1) { + kdDebug()<<"Found at "<<pos << " length "<<count << " with " << _r1.pattern()<< endl; + QString s1 = msg.mid(pos,count); + kdDebug()<<"Sub: "<<s1 << endl; + kdDebug()<<_r1.cap(1) << endl; + QString rep = genReplace(s1); + kdDebug()<<"Replace with "<<rep << endl; + msg = msg.replace(pos,count,rep); + + pos = _r1.search(msg,pos+rep.length()); + count = _r1.matchedLength(); + } +} + +/*! + \fn SvnLogDlgImp::slotItemClicked(QListViewItem*) + */ +void SvnLogDlgImp::slotSelectionChanged(QListViewItem*_it) +{ + if (!_it) { + m_DispPrevButton->setEnabled(false); + buttonListFiles->setEnabled(false); + buttonBlame->setEnabled(false); + m_ChangedList->clear(); + return; + } + LogListViewItem* k = static_cast<LogListViewItem*>( _it ); + if (k->numChangedEntries()==0) { + buttonListFiles->setEnabled(true); + if (m_ChangedList->isVisible()){ + m_ChangedList->hide(); + } + } else { + buttonListFiles->setEnabled(false); + if (!m_ChangedList->isVisible()){ + m_ChangedList->show(); + } + } + QString msg = k->message(); + replaceBugids(msg); + m_LogDisplay->setText(msg); + + k->showChangedEntries(m_ChangedList); + buttonBlame->setEnabled(true); + + k = static_cast<LogListViewItem*>(_it->nextSibling()); + if (!k) { + m_DispPrevButton->setEnabled(false); + } else { + m_DispPrevButton->setEnabled(true); + } +} + + +/*! + \fn SvnLogDlgImp::slotDispPrevious() + */ +void SvnLogDlgImp::slotDispPrevious() +{ + LogListViewItem* k = static_cast<LogListViewItem*>(m_LogView->selectedItem()); + if (!k) { + m_DispPrevButton->setEnabled(false); + return; + } + LogListViewItem* p = static_cast<LogListViewItem*>(k->nextSibling()); + if (!p) { + m_DispPrevButton->setEnabled(false); + return; + } + QString s,e; + s = _base+k->realName(); + e = _base+p->realName(); + emit makeDiff(e,p->rev(),s,k->rev(),this); +} + + +/*! + \fn SvnLogDlgImp::saveSize() + */ +void SvnLogDlgImp::saveSize() +{ + int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); + KConfigGroupSaver cs(Kdesvnsettings::self()->config(), groupName); + QSize sizeToSave = size(); + Kdesvnsettings::self()->config()->writeEntry( QString::fromLatin1("Width %1").arg( desk.width()), + QString::number( sizeToSave.width()), true, false); + Kdesvnsettings::self()->config()->writeEntry( QString::fromLatin1("Height %1").arg( desk.height()), + QString::number( sizeToSave.height()), true, false); +} + +QSize SvnLogDlgImp::dialogSize() +{ + int w, h; + int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); + w = sizeHint().width(); + h = sizeHint().height(); + KConfigGroupSaver cs(Kdesvnsettings::self()->config(), groupName); + w = Kdesvnsettings::self()->config()->readNumEntry( QString::fromLatin1("Width %1").arg( desk.width()), w ); + h = Kdesvnsettings::self()->config()->readNumEntry( QString::fromLatin1("Height %1").arg( desk.height()), h ); + return( QSize( w, h ) ); +} + +void SvnLogDlgImp::slotItemClicked(int button,QListViewItem*item,const QPoint &,int) +{ + if (!item) { + m_ChangedList->clear(); + return; + } + LogListViewItem*which = static_cast<LogListViewItem*>(item); + /* left mouse */ + if (button == 1&&!m_ControlKeyDown) { + if (m_first) m_first->setText(0,""); + if (m_first == which) { + m_first = 0; + } else { + m_first = which; + m_first->setText(0,"1"); + } + if (m_first==m_second) { + m_second = 0; + } + m_startRevButton->setRevision(which->rev()); + + /* other mouse or ctrl hold*/ + } else { + if (m_second) m_second->setText(0,""); + if (m_second == which) { + m_second = 0; + } else { + m_second = which; + m_second->setText(0,"2"); + } + if (m_first==m_second) { + m_first = 0; + } + m_endRevButton->setRevision(which->rev()); + } + m_DispSpecDiff->setEnabled(m_first!=0 && m_second!=0); +} + +void SvnLogDlgImp::slotRevisionSelected() +{ + m_goButton->setFocus(); + //m_DispSpecDiff->setEnabled( m_first && m_second && m_first != m_second); +} + +void SvnLogDlgImp::slotDispSelected() +{ + if (!m_first || !m_second) return; + emit makeDiff(_base+m_first->realName(),m_first->rev(),_base+m_second->realName(),m_second->rev(),this); +} + +bool SvnLogDlgImp::getSingleLog(svn::LogEntry&t,const svn::Revision&r,const QString&what,const svn::Revision&peg,QString&root) +{ + root = _base; + if (m_Entries->find(r.revnum()) == m_Entries->end()) + { + return m_Actions->getSingleLog(t,r,what,peg,root); + } + t=(*m_Entries)[r.revnum()]; + return true; +} + +void SvnLogDlgImp::slotGetLogs() +{ + kdDebug()<<"Displog: "<<m_peg.toString()<<endl; + svn::SharedPointer<svn::LogEntriesMap> lm = m_Actions->getLog(m_startRevButton->revision(), + m_endRevButton->revision(),m_peg, + _base+"/"+_name,Kdesvnsettings::self()->log_always_list_changed_files(),0,this); + if (lm) { + dispLog(lm); + } +} + +void SvnLogDlgImp::slotListEntries() +{ + LogListViewItem * it = static_cast<LogListViewItem*>(m_LogView->selectedItem()); + if (!it||it->numChangedEntries()>0||!m_Actions) { + buttonListFiles->setEnabled(false); + return; + } + svn::SharedPointer<svn::LogEntriesMap>_log = m_Actions->getLog(it->rev(),it->rev(),it->rev(),_name,true,0); + if (!_log) { + return; + } + if (_log->count()>0) { + it->setChangedEntries((*_log)[it->rev()]); + it->showChangedEntries(m_ChangedList); + if (!m_ChangedList->isVisible()) m_ChangedList->show(); + } + buttonListFiles->setEnabled(false); +} + +void SvnLogDlgImp::keyPressEvent (QKeyEvent * e) +{ + if (!e) return; + if (e->text().isEmpty()&&e->key()==Key_Control) { + m_ControlKeyDown = true; + } + SvnLogDialogData::keyPressEvent(e); +} + +void SvnLogDlgImp::keyReleaseEvent (QKeyEvent * e) +{ + if (!e) return; + if (e->text().isEmpty()&&e->key()==Qt::Key_Control) { + m_ControlKeyDown = false; + } + SvnLogDialogData::keyReleaseEvent(e); +} + +void SvnLogDlgImp::slotBlameItem() +{ + LogListViewItem* k = static_cast<LogListViewItem*>(m_LogView->selectedItem()); + if (!k) { + buttonBlame->setEnabled(false); + return; + } + svn::Revision start(svn::Revision::START); + m_Actions->makeBlame(start,k->rev(),_base+k->realName(),kapp->activeModalWidget(),k->rev(),this); +} + +void SvnLogDlgImp::slotEntriesSelectionChanged() +{ +} + +void SvnLogDlgImp::slotSingleContext(QListViewItem*_item, const QPoint & e, int) +{ + if (!_item) + { + return; + } + + LogChangePathItem* item = static_cast<LogChangePathItem*>(_item); + LogListViewItem* k = static_cast<LogListViewItem*>(m_LogView->selectedItem()); + if (!k) { + kdDebug()<<"????"<<endl; + return; + } + QPopupMenu popup; + QString name = item->path(); + QString action = item->action(); + QString source =item->revision()>-1?item->source():item->path(); + svn_revnum_t prev = item->revision()>0?item->revision():k->rev()-1; + if (action != "D") { + popup.insertItem(i18n("Annotate"),101); + if (action != "A" || item->revision()>-1) { + popup.insertItem(i18n("Diff previous"),102); + } + popup.insertItem(i18n("Cat this version"),103); + } + int r = popup.exec(e); + svn::Revision start(svn::Revision::START); + switch (r) + { + case 101: + { + m_Actions->makeBlame(start,k->rev(),_base+name,kapp->activeModalWidget(),k->rev(),this); + break; + } + case 102: + { + emit makeDiff(_base+source,prev,_base+name,k->rev(),this); + break; + } + case 103: + { + emit makeCat(k->rev(),_base+source,source,k->rev(),kapp->activeModalWidget()); + } + default: + break; + } +} + +void SvnLogDlgImp::slotSingleDoubleClicked(QListViewItem*_item) +{ + if (!_item) + { + return; + } + + LogChangePathItem* item = static_cast<LogChangePathItem*>(_item); + LogListViewItem* k = static_cast<LogListViewItem*>(m_LogView->selectedItem()); + if (!k) { + kdDebug()<<"????"<<endl; + return; + } + QString name = item->path(); + QString action = item->action(); + QString source =item->revision()>-1?item->source():item->path(); + //svn_revnum_t prev = item->revision()>0?item->revision():k->rev()-1; + svn::Revision start(svn::Revision::START); + if (action != "D") { + m_Actions->makeBlame(start,k->rev(),_base+name,kapp->activeModalWidget(),k->rev(),this); + } +} + +#include "svnlogdlgimp.moc" diff --git a/src/svnfrontend/svnlogdlgimp.h b/src/svnfrontend/svnlogdlgimp.h new file mode 100644 index 0000000..620f894 --- /dev/null +++ b/src/svnfrontend/svnlogdlgimp.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNLOGDLGIMP_H +#define SVNLOGDLGIMP_H + +#include "svnlogdlg.h" +#include "simple_logcb.h" +#include "src/svnqt/log_entry.hpp" +#include "src/svnqt/client.hpp" +#include "src/svnqt/shared_pointer.hpp" + +#include <qsize.h> +#include <qregexp.h> + +class LogListViewItem; +class SvnActions; + +class SvnLogDlgImp: public SvnLogDialogData,public SimpleLogCb +{ +Q_OBJECT +public: + SvnLogDlgImp(SvnActions*,QWidget *parent = 0, const char *name = 0,bool modal=true); + virtual ~SvnLogDlgImp(); + void dispLog(const svn::SharedPointer<svn::LogEntriesMap>&,const QString&,const QString&,const svn::Revision&peg,const QString&pegUrl); + void saveSize(); + QSize dialogSize(); + + virtual bool getSingleLog(svn::LogEntry&t,const svn::Revision&r,const QString&what,const svn::Revision&peg,QString&root); + +signals: + void makeDiff(const QString&,const svn::Revision&,const QString&,const svn::Revision&,QWidget*); + void makeCat(const svn::Revision&,const QString&,const QString&,const svn::Revision&,QWidget*); + +protected slots: + virtual void slotSelectionChanged(QListViewItem*); +protected slots: + virtual void slotDispPrevious(); + virtual void slotDispSelected(); + virtual void slotItemClicked(int,QListViewItem*,const QPoint &,int); + virtual void slotRevisionSelected(); +protected: + QString _name; + QString _base; + static const char* groupName; + LogListViewItem *m_first,*m_second; + SvnActions*m_Actions; + bool m_ControlKeyDown; + virtual void keyPressEvent (QKeyEvent * e); + virtual void keyReleaseEvent (QKeyEvent * e); + virtual void slotBlameItem(); + svn::SharedPointer<svn::LogEntriesMap> m_Entries; + QString _bugurl; + + void dispLog(const svn::SharedPointer<svn::LogEntriesMap>&); + + QRegExp _r1,_r2; + +protected slots: + virtual void slotListEntries(); + virtual void slotEntriesSelectionChanged(); + virtual void slotSingleContext(QListViewItem*, const QPoint &, int); + virtual void slotSingleDoubleClicked(QListViewItem*); + virtual void slotGetLogs(); + +protected: + void replaceBugids(QString&msg); + QString genReplace(const QString&); + svn::Revision m_peg; + svn::Path m_PegUrl; +}; + +#endif diff --git a/src/svnfrontend/tcontextlistener.cpp b/src/svnfrontend/tcontextlistener.cpp new file mode 100644 index 0000000..0d90de2 --- /dev/null +++ b/src/svnfrontend/tcontextlistener.cpp @@ -0,0 +1,319 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "tcontextlistener.h" + +#include "ccontextlistener.h" +#include "src/ksvnwidgets/authdialogimpl.h" +#include "src/ksvnwidgets/logmsg_impl.h" +#include "src/ksvnwidgets/ssltrustprompt_impl.h" +#include "src/helpers/stringhelper.h" +#include "threadcontextlistenerdata.h" + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> + +ThreadContextListener::ThreadContextListener(QObject* parent, const char* name) + : CContextListener(parent, name) +{ + m_Data = new ThreadContextListenerData; +} + +ThreadContextListener::~ThreadContextListener() +{ + delete m_Data; +} + +QMutex*ThreadContextListener::callbackMutex() +{ + static QMutex s_CallbackMutex; + return &s_CallbackMutex; +} + +bool ThreadContextListener::contextGetLogin(const QString& realm, QString& username, QString& password, bool& maySave) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + ThreadContextListenerData::slogin_data _data; + _data.realm=realm; + _data.user=username; + _data.password=password; + _data.maysave=maySave; + _data.ok=false; + + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_LOGIN_PROMPT); + void*t = (void*)&_data; + ev->setData(t); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + username = _data.user; + password = _data.password; + maySave = _data.maysave; + return _data.ok; +} + +bool ThreadContextListener::contextGetSavedLogin(const QString & realm,QString & username,QString & password) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + ThreadContextListenerData::slogin_data _data; + _data.realm=realm; + _data.user=username; + _data.password=password; + _data.maysave=false; + _data.ok=false; + + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_LOGIN_SAVED); + void*t = (void*)&_data; + ev->setData(t); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + username = _data.user; + password = _data.password; + return _data.ok; +} + +bool ThreadContextListener::contextGetLogMessage(QString& msg,const svn::CommitItemList&_items) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + ThreadContextListenerData::slog_message log; + log.ok = false; + log.msg = ""; + log._items = &_items; + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_LOGMSG_PROMPT); + void*t = (void*)&log; + ev->setData(t); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + msg = log.msg; + return log.ok; +} + +bool ThreadContextListener::contextSslClientCertPrompt(QString& certFile) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + + ThreadContextListenerData::scert_file scertf; + scertf.ok = false; + scertf.certfile=""; + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_CERT_SELECT_PROMPT); + ev->setData((void*)&scertf); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + certFile = scertf.certfile; + return scertf.ok; +} + +bool ThreadContextListener::contextSslClientCertPwPrompt(QString& password, const QString& realm, bool& maySave) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + ThreadContextListenerData::scert_pw scert_data; + scert_data.ok=false; + scert_data.maysave=false; + scert_data.password=""; + scert_data.realm=realm; + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_CERT_PW_PROMPT); + ev->setData((void*)&scert_data); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + password = scert_data.password; + maySave = scert_data.maysave; + return scert_data.ok; +} + +svn::ContextListener::SslServerTrustAnswer ThreadContextListener::contextSslServerTrustPrompt(const SslServerTrustData& data, apr_uint32_t&/* acceptedFailures*/) +{ + QMutexLocker lock(callbackMutex()); + m_WaitMutex.lock(); + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_SSL_TRUST_PROMPT); + ThreadContextListenerData::strust_answer trust_answer; + trust_answer.m_SslTrustAnswer=DONT_ACCEPT; + trust_answer.m_Trustdata = &data; + ev->setData((void*)&trust_answer); + kapp->postEvent(this,ev); + m_Data->m_trustpromptWait.wait(&m_WaitMutex); + m_WaitMutex.unlock(); + return trust_answer.m_SslTrustAnswer; +} + +void ThreadContextListener::contextNotify(const QString&aMsg) +{ + QMutexLocker lock(callbackMutex()); + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_NOTIFY); + // receiver must delete data! + ThreadContextListenerData::snotify* _notify = new ThreadContextListenerData::snotify(); + _notify->msg = aMsg; + ev->setData((void*)_notify); + kapp->postEvent(this,ev); +} + +/*! + \fn ThreadContextListener::contextProgress(long long int current, long long int max) + */ +void ThreadContextListener::contextProgress(long long int current, long long int max) +{ + if (m_Data->noProgress||current==0) { + return; + } + QMutexLocker lock(callbackMutex()); + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_NOTIFY); + // receiver must delete data! + ThreadContextListenerData::snotify* _notify = new ThreadContextListenerData::snotify(); + QString msg; + QString s1 = helpers::ByteToString()(current); + if (max>-1) { + QString s2 = helpers::ByteToString()(max); + msg = i18n("%1 of %2 transferred.").arg(s1).arg(s2); + } else { + msg = i18n("%1 transferred.").arg(s1); + } + _notify->msg = msg; + ev->setData((void*)_notify); + kapp->postEvent(this,ev); +} + +void ThreadContextListener::sendTick() +{ + QMutexLocker lock(callbackMutex()); + QCustomEvent*ev = new QCustomEvent(EVENT_THREAD_NOTIFY); + // receiver must delete data! + ThreadContextListenerData::snotify* _notify = new ThreadContextListenerData::snotify(); + _notify->msg = ""; + ev->setData((void*)_notify); + kapp->postEvent(this,ev); +} + +/* methods below may only called from mainthread! (via event) */ +void ThreadContextListener::event_contextGetLogin(void*data) +{ + QMutexLocker lock(&m_WaitMutex); + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::slogin_data*_data = (ThreadContextListenerData::slogin_data*)data; + + _data->ok = CContextListener::contextGetLogin(_data->realm, _data->user, _data->password, _data->maysave); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextGetSavedLogin(void*data) +{ + QMutexLocker lock(&m_WaitMutex); + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::slogin_data*_data = (ThreadContextListenerData::slogin_data*)data; + _data->ok = CContextListener::contextGetSavedLogin(_data->realm, _data->user, _data->password); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextGetLogMessage(void * data) +{ + QMutexLocker lock(&m_WaitMutex); + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::slog_message * _log = (ThreadContextListenerData::slog_message*)data; + + _log->ok = CContextListener::contextGetLogMessage(_log->msg,(_log->_items?*(_log->_items):svn::CommitItemList())); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextSslClientCertPrompt(void*data) +{ + QMutexLocker lock(&m_WaitMutex); + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::scert_file*scertf = (ThreadContextListenerData::scert_file*)data; + scertf->ok = CContextListener::contextSslClientCertPrompt(scertf->certfile); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextSslClientCertPwPrompt(void*data) +{ + QMutexLocker lock(&m_WaitMutex); + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::scert_pw*scert_data = (ThreadContextListenerData::scert_pw*)data; + scert_data->ok = CContextListener::contextSslClientCertPwPrompt(scert_data->password, scert_data->realm, scert_data->maysave); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextSslServerTrustPrompt(void*data) +{ + QMutexLocker lock(&m_WaitMutex); + /* + * m_SslTrustAnswer is made threadsafe due the m_trustpromptWait - the calling thread waits until wakeAll is called! + */ + if (!data) { + m_Data->m_trustpromptWait.wakeAll(); + return; + } + ThreadContextListenerData::strust_answer*_data = (ThreadContextListenerData::strust_answer*)data; + apr_uint32_t _t = _data->m_Trustdata->failures; + _data->m_SslTrustAnswer = CContextListener::contextSslServerTrustPrompt(*(_data->m_Trustdata),_t); + m_Data->m_trustpromptWait.wakeAll(); +} + +void ThreadContextListener::event_contextNotify(void*data) +{ + if (!data) { + return; + } + ThreadContextListenerData::snotify* _notify = (ThreadContextListenerData::snotify*)data; + CContextListener::contextNotify(_notify->msg); + delete _notify; +} + +void ThreadContextListener::customEvent(QCustomEvent*ev) +{ + if (ev->type()==EVENT_THREAD_SSL_TRUST_PROMPT) { + event_contextSslServerTrustPrompt(ev->data()); + }else if (ev->type()==EVENT_THREAD_LOGIN_PROMPT) { + event_contextGetLogin(ev->data()); + }else if (ev->type()==EVENT_THREAD_LOGMSG_PROMPT) { + event_contextGetLogMessage(ev->data()); + }else if (ev->type()==EVENT_THREAD_CERT_PW_PROMPT) { + event_contextSslClientCertPwPrompt(ev->data()); + }else if (ev->type()==EVENT_THREAD_CERT_SELECT_PROMPT) { + event_contextSslClientCertPrompt(ev->data()); + }else if (ev->type()==EVENT_THREAD_NOTIFY) { + event_contextNotify(ev->data()); + } else if (ev->type() == EVENT_THREAD_LOGIN_SAVED) { + event_contextGetSavedLogin(ev->data()); + } +} + +#include "tcontextlistener.moc" diff --git a/src/svnfrontend/tcontextlistener.h b/src/svnfrontend/tcontextlistener.h new file mode 100644 index 0000000..92d69b4 --- /dev/null +++ b/src/svnfrontend/tcontextlistener.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef TCONTEXTLISTENER_H +#define TCONTEXTLISTENER_H + +#include "eventnumbers.h" + +#include "ccontextlistener.h" + +#include <qevent.h> +#include <qmutex.h> +#include <qwaitcondition.h> + +class ThreadContextListenerData; + +/** +@author Rajko Albrecht +*/ +class ThreadContextListener : public CContextListener +{ + Q_OBJECT +public: + ThreadContextListener(QObject* parent, const char* name=0); + + virtual ~ThreadContextListener(); + + virtual bool contextGetLogin(const QString& realm, QString& username, QString& password, bool& maySave); + virtual bool contextGetSavedLogin(const QString & realm,QString & username,QString & password); + + virtual bool contextGetLogMessage(QString& msg,const svn::CommitItemList&); + virtual bool contextSslClientCertPrompt(QString& certFile); + virtual bool contextSslClientCertPwPrompt(QString& password, const QString& realm, bool& maySave); + virtual svn::ContextListener::SslServerTrustAnswer contextSslServerTrustPrompt(const SslServerTrustData& data, apr_uint32_t& acceptedFailures); + virtual void contextNotify(const QString&aMsg); + virtual void sendTick(); + virtual void contextProgress(long long int current, long long int max); + + static QMutex*callbackMutex(); + +protected: + virtual void event_contextGetLogin(void*_data); + virtual void event_contextGetSavedLogin(void*_data); + virtual void event_contextGetLogMessage(void*data); + virtual void event_contextSslClientCertPrompt(void*data); + virtual void event_contextSslClientCertPwPrompt(void*data); + virtual void event_contextSslServerTrustPrompt(void* data); + virtual void event_contextNotify(void*data); + virtual void customEvent(QCustomEvent*); + + /* stores all internals */ + QMutex m_WaitMutex; + ThreadContextListenerData*m_Data; +}; + +#endif diff --git a/src/svnfrontend/threadcontextlistenerdata.cpp b/src/svnfrontend/threadcontextlistenerdata.cpp new file mode 100644 index 0000000..2cb0d49 --- /dev/null +++ b/src/svnfrontend/threadcontextlistenerdata.cpp @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "threadcontextlistenerdata.h" + +ThreadContextListenerData::ThreadContextListenerData() + :noProgress(true) +{ +} + + +ThreadContextListenerData::~ThreadContextListenerData() +{ +} diff --git a/src/svnfrontend/threadcontextlistenerdata.h b/src/svnfrontend/threadcontextlistenerdata.h new file mode 100644 index 0000000..b225161 --- /dev/null +++ b/src/svnfrontend/threadcontextlistenerdata.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef THREADCONTEXTLISTENERDATA_H +#define THREADCONTEXTLISTENERDATA_H + +#include "src/svnqt/context_listener.hpp" + +#include <qthread.h> +#include <qstring.h> + +/** +@author Rajko Albrecht +*/ +class ThreadContextListenerData{ +public: + ThreadContextListenerData(); + + virtual ~ThreadContextListenerData(); + + /* sometimes suppress progress messages */ + bool noProgress; + + /* only one callback at time */ + QWaitCondition m_trustpromptWait; + + /* safed due condition above */ + /* this variables are for the event handling across threads */ + /* Trust ssl realm* */ + struct strust_answer { + svn::ContextListener::SslServerTrustAnswer m_SslTrustAnswer; + const svn::ContextListener::SslServerTrustData*m_Trustdata; + }; + + + /* login into server */ + struct slogin_data + { + QString user,password,realm; + bool maysave,ok; + }; + + struct slog_message + { + QString msg; + bool ok; + const svn::CommitItemList*_items; + slog_message(){_items = 0;} + }; + + struct scert_pw + { + QString password,realm; + bool ok,maysave; + }; + + struct scert_file + { + QString certfile; + bool ok; + }; + + struct snotify + { + QString msg; + }; +}; + +#endif diff --git a/src/svnqt/CMakeLists.txt b/src/svnqt/CMakeLists.txt new file mode 100644 index 0000000..bf50a6f --- /dev/null +++ b/src/svnqt/CMakeLists.txt @@ -0,0 +1,205 @@ +SET(SOURCES + apr.cpp + client_annotate.cpp + client_cat.cpp + client.cpp + client_diff.cpp + client_ls.cpp + client_modify.cpp + client_property.cpp + client_status.cpp + context.cpp + datetime.cpp + dirent.cpp + entry.cpp + exception.cpp + log_entry.cpp + path.cpp + pool.cpp + revision.cpp + status.cpp + targets.cpp + url.cpp + version_check.cpp + wc.cpp + lock_entry.cpp + client_lock.cpp + info_entry.cpp + client_impl.cpp + contextdata.cpp + commititem.cpp + repository.cpp + repositorydata.cpp + repositorylistener.cpp + svnstream.cpp + diff_data.cpp + svnfilestream.cpp + stringarray.cpp + diffoptions.cpp + conflictdescription.cpp + conflictresult.cpp + client_merge.cpp + cache/LogCache.cpp + cache/ReposLog.cpp + cache/DatabaseException.hpp + cache/DatabaseException.cpp + ) + +IF (NOT QT4_FOUND) + IF (SQLITE_FOUND) + MESSAGE(STATUS "Build own sqlite3 database modul") + SET(SOURCES + ${SOURCES} + cache/sqlite3/qsqlcachedresult.cpp + cache/sqlite3/qsql_sqlite3.cpp + cache/sqlite3/qsqlcachedresult.h + cache/sqlite3/qsql_sqlite3.h + ) + ELSE (SQLITE_FOUND) + MESSAGE(SEND_ERROR "The QT3 version requires sqlite3 but could not found") + ENDIF (SQLITE_FOUND) +ELSE (NOT QT4_FOUND) + MESSAGE(STATUS "Build with QT4.") + ADD_DEFINITIONS(-DNO_SQLITE3) +ENDIF (NOT QT4_FOUND) + +SET(CACHEINST_HEADERS + cache/LogCache.hpp + cache/ReposLog.hpp + cache/DatabaseException.hpp +) + +SET(INST_HEADERS + annotate_line.hpp + apr.hpp + check.hpp + client.hpp + commititem.hpp + context.hpp + context_listener.hpp + datetime.hpp + dirent.hpp + entry.hpp + exception.hpp + info_entry.hpp + lock_entry.hpp + log_entry.hpp + path.hpp + pool.hpp + repository.hpp + repositorylistener.hpp + revision.hpp + smart_pointer.hpp + shared_pointer.hpp + status.hpp + svnfilestream.hpp + svnstream.hpp + svnqttypes.hpp + targets.hpp + url.hpp + version_check.hpp + wc.hpp + stringarray.hpp + diffoptions.hpp + conflictdescription.hpp + conflictresult.hpp + ) + +FILE(GLOB svnhdr RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.hpp") +SET(svnhdr ${svnhdr} ${CACHE_INST_HEADERS}) + +IF(QT4_FOUND) + MESSAGE(STATUS "Qt: ${QT_LIBRARY_DIR}") + MESSAGE(STATUS "Qt: ${QT_QTCORE_LIBRARY}") + SET(TOUTF8 "toUtf8") + SET(FROMUTF8 "fromUtf8") + SET(QLIST "QList") + SET(TOASCII "toAscii") + SET(HOMEDIR "homePath") + SET(svnqt-name svnqt-qt4) + SET(QDATABASE "QSqlDatabase") + SET(QLONG "qlonglong") +ELSE(QT4_FOUND) + IF(QT_FOUND) + SET(TOUTF8 "utf8") + SET(FROMUTF8 "fromUtf8") + SET(QLIST "QValueList") + SET(TOASCII "latin1") + SET(HOMEDIR "homeDirPath") + SET(QDATABASE "QSqlDatabase*") + SET(QLONG "Q_LLONG") + ENDIF(QT_FOUND) + SET(svnqt-name svnqt) +ENDIF(QT4_FOUND) + +IF (HAVE_GCC_VISIBILITY) + SET(_SVNQT_EXPORT "__attribute__ ((visibility(\"default\")))") + SET(_SVNQT_NOEXPORT "__attribute__ ((visibility(\"hidden\")))") +ENDIF (HAVE_GCC_VISIBILITY) +IF (WIN32) + SET(_SVNQT_EXPORT "__declspec(dllexport)") +ENDIF (WIN32) + +CONFIGURE_FILE( + "${CMAKE_CURRENT_SOURCE_DIR}/svnqt_defines.hpp.in" + "${CMAKE_CURRENT_BINARY_DIR}/svnqt_defines.hpp" + IMMEDIATE + @ONLY) + +SET(INST_HEADERS ${INST_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/svnqt_defines.hpp) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(${svnqt-name} SHARED ${SOURCES} ${svnhdr}) +IF(WIN32) + ADD_DEFINITIONS(-D_USE_32BIT_TIME_T) +ELSE(WIN32) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}) + SET_TARGET_PROPERTIES(${svnqt-name} + PROPERTIES + COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) +ENDIF(WIN32) + +SET(LIB_MAJOR 4) +SET(LIB_MINOR 2) +SET(LIB_RELEASE 2) + +SET(_soversion ${LIB_MAJOR}.${LIB_MINOR}.${LIB_RELEASE}) + +SET_TARGET_PROPERTIES(${svnqt-name} PROPERTIES + SOVERSION ${LIB_MAJOR} + VERSION ${_soversion}) + +SET(ALL_LINKFLAGS ${APR_EXTRA_LIBFLAGS}) +SET(ALL_LINKFLAGS "${ALL_LINKFLAGS} ${APU_EXTRA_LIBFLAGS}") +SET_TARGET_PROPERTIES(${svnqt-name} PROPERTIES LINK_FLAGS "${ALL_LINKFLAGS} ${LINK_NO_UNDEFINED}") +TARGET_LINK_LIBRARIES(${svnqt-name} ${QT_LIBRARIES} ${SUBVERSION_ALL_LIBS}) + +IF (SQLITE_FOUND AND NOT QT4_FOUND) + TARGET_LINK_LIBRARIES(${svnqt-name} ${SQLITE_LIBRARIES}) + INCLUDE_DIRECTORIES(SQLITE_INCLUDE_DIR) +ELSE (SQLITE_FOUND AND NOT QT4_FOUND) + TARGET_LINK_LIBRARIES(${svnqt-name} ${QT_QTSQL_LIBRARY}) +ENDIF (SQLITE_FOUND AND NOT QT4_FOUND) + +IF (WIN32) + TARGET_LINK_LIBRARIES( ${svnqt-name} wsock32.lib ) +ENDIF (WIN32) + +# Just a small linking test +IF (BUILD_TESTS) + ADD_EXECUTABLE(testlink testmain.cpp) + TARGET_LINK_LIBRARIES(testlink ${svnqt-name}) +ENDIF (BUILD_TESTS) + +# install rules +# in win32 we don't install it +IF(NOT WIN32) + INSTALL(TARGETS ${svnqt-name} DESTINATION ${LIB_INSTALL_DIR}) + INSTALL(FILES ${INST_HEADERS} DESTINATION include/${svnqt-name}) + INSTALL(FILES ${CACHEINST_HEADERS} DESTINATION include/${svnqt-name}/cache) +ENDIF(NOT WIN32) + +IF (BUILD_TESTS) + ADD_SUBDIRECTORY(tests) + ADD_SUBDIRECTORY(cache/test) +ENDIF (BUILD_TESTS) diff --git a/src/svnqt/annotate_line.hpp b/src/svnqt/annotate_line.hpp new file mode 100644 index 0000000..c8a0a6f --- /dev/null +++ b/src/svnqt/annotate_line.hpp @@ -0,0 +1,159 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#ifndef _SVNCPP_ANNOTATE_LINE_HPP_ +#define _SVNCPP_ANNOTATE_LINE_HPP_ + +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> +#include <qdatetime.h> + +namespace svn +{ + /** + * This class holds the data for one line in an annotation + */ + class AnnotateLine + { + public: + AnnotateLine (QLONG line_no, + QLONG revision, + const char *author, + const char *date, + const char *line) + : m_line_no (line_no), m_revision (revision), + m_date( (date&&strlen(date))?QDateTime::fromString(QString::FROMUTF8(date),Qt::ISODate):QDateTime()), + m_line(line?line:""),m_author(author?author:""), + m_merge_revision(-1), + m_merge_date(QDateTime()), + m_merge_author(""),m_merge_path("") + + { + } + + AnnotateLine (QLONG line_no, + QLONG revision, + const char *author, + const char *date, + const char *line, + QLONG merge_revision, + const char *merge_author, + const char *merge_date, + const char *merge_path + ) + : m_line_no (line_no), m_revision (revision), + m_date( (date&&strlen(date))?QDateTime::fromString(QString::FROMUTF8(date),Qt::ISODate):QDateTime()), + m_line(line?line:""),m_author(author?author:""), + m_merge_revision(merge_revision), + m_merge_date( (merge_date&&strlen(merge_date))?QDateTime::fromString(QString::FROMUTF8(merge_date),Qt::ISODate):QDateTime()), + m_merge_author(merge_author?merge_author:""),m_merge_path(merge_path?merge_path:"") + { + } + + AnnotateLine ( const AnnotateLine &other) + : m_line_no (other.m_line_no), m_revision (other.m_revision), m_date (other.m_date), + m_line (other.m_line), m_author (other.m_author) + { + } + AnnotateLine() + : m_line_no(0),m_revision(-1),m_date(), + m_line(), m_author() + { + } + + /** + * destructor + */ + virtual ~AnnotateLine () + { + } + + QLONG + lineNumber () const + { + return m_line_no; + } + QLONG + revision () const + { + return m_revision; + } + + + const QByteArray & + author () const + { + return m_author; + } + + + const QDateTime & + date () const + { + return m_date; + } + + + const QByteArray & + line () const + { + return m_line; + } + + protected: + QLONG m_line_no; + QLONG m_revision; + QDateTime m_date; +#if QT_VERSION < 0x040000 + QCString m_line; + QCString m_author; +#else + QByteArray m_line; + QByteArray m_author; +#endif + + QLONG m_merge_revision; + QDateTime m_merge_date; +#if QT_VERSION < 0x040000 + QCString m_merge_author; + QCString m_merge_path; +#else + QByteArray m_merge_author; + QByteArray m_merge_path; +#endif + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/apr.cpp b/src/svnqt/apr.cpp new file mode 100644 index 0000000..ca531a0 --- /dev/null +++ b/src/svnqt/apr.cpp @@ -0,0 +1,52 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// apr +#include "apr_general.h" + +// svncpp +#include "apr.hpp" + + +/** + * SvnCpp namespace. + */ +namespace svn +{ + Apr::Apr () + { + apr_initialize (); + } + + Apr::~Apr () + { + apr_terminate (); + } +} diff --git a/src/svnqt/apr.hpp b/src/svnqt/apr.hpp new file mode 100644 index 0000000..bb6655a --- /dev/null +++ b/src/svnqt/apr.hpp @@ -0,0 +1,69 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_APR_H_ +#define _SVNCPP_APR_H_ + +namespace svn +{ + + /** + * APR class. Include this class in your application for apr + * support. + */ + class Apr + { + public: + /** + * Default constructor. Initializes APR + */ + Apr (); + + /** + * Destructor. Terminates APR + */ + ~Apr (); + + private: + /** Disallow copy constructor */ + Apr (const Apr &); + + /** Disallow assignment operator */ + Apr & + operator = (const Apr &); + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/cache/DatabaseException.cpp b/src/svnqt/cache/DatabaseException.cpp new file mode 100644 index 0000000..85812ab --- /dev/null +++ b/src/svnqt/cache/DatabaseException.cpp @@ -0,0 +1,12 @@ +#include "DatabaseException.hpp" + +/*! + \fn svn::cache::DatabaseException::DatabaseException(const QString&msg,int aNumber)throw() + */ +svn::cache::DatabaseException::DatabaseException(const QString&msg,int aNumber)throw() + : Exception(msg),m_number(aNumber) +{ + if (aNumber>-1) { + setMessage(QString("(Code %1) %2").arg(aNumber).arg(msg)); + } +} diff --git a/src/svnqt/cache/DatabaseException.hpp b/src/svnqt/cache/DatabaseException.hpp new file mode 100644 index 0000000..85e5ce4 --- /dev/null +++ b/src/svnqt/cache/DatabaseException.hpp @@ -0,0 +1,35 @@ +#ifndef _DATABASE_EXCEPTION_HPP +#define _DATABASE_EXCEPTION_HPP + +#include "svnqt/exception.hpp" + +namespace svn +{ +namespace cache +{ + +class SVNQT_EXPORT DatabaseException:public svn::Exception +{ + private: + DatabaseException()throw(); + int m_number; + + public: + DatabaseException(const QString&msg)throw() + : Exception(msg),m_number(-1) + {} + + DatabaseException(const DatabaseException&src)throw() + : Exception(src.msg()),m_number(src.number()) + {} + DatabaseException(const QString&msg,int aNumber)throw(); + virtual ~DatabaseException()throw(){} + int number() const + { + return m_number; + } +}; + +} +} +#endif diff --git a/src/svnqt/cache/LogCache.cpp b/src/svnqt/cache/LogCache.cpp new file mode 100644 index 0000000..6356c6f --- /dev/null +++ b/src/svnqt/cache/LogCache.cpp @@ -0,0 +1,468 @@ +#include "LogCache.hpp" + +#include <qdir.h> +#include <qsql.h> +#include <qsqldatabase.h> +#if QT_VERSION < 0x040000 +#include <qthreadstorage.h> +#else +#include <QMutex> +#include <QThreadStorage> +#include <QSqlError> +#include <QSqlQuery> +#include <QVariant> +#endif +#include <qmap.h> + +#include "svnqt/path.hpp" +#include "svnqt/cache/DatabaseException.hpp" + +#ifndef NO_SQLITE3 +#include "sqlite3/qsql_sqlite3.h" +#define SQLTYPE "QSQLITE3" +#else +#define SQLTYPE "QSQLITE" +#endif + +#define SQLMAIN "logmain-logcache" +#define SQLMAINTABLE "logdb" + +namespace svn { +namespace cache { + +LogCache* LogCache::mSelf = 0; + +class ThreadDBStore +{ +public: + ThreadDBStore(){ +#if QT_VERSION < 0x040000 + m_DB=0; +#else + m_DB=QSqlDatabase(); +#endif + } + ~ThreadDBStore(){ +#if QT_VERSION < 0x040000 + m_DB=0; +#else + m_DB=QSqlDatabase(); +#endif + QSqlDatabase::removeDatabase(key); + QMap<QString,QString>::Iterator it; + for (it=reposCacheNames.begin();it!=reposCacheNames.end();++it) { +#if QT_VERSION < 0x040000 + QSqlDatabase::removeDatabase(it.data()); +#else + QSqlDatabase::removeDatabase(it.value()); +#endif + } + } + + QDataBase m_DB; + QString key; + QMap<QString,QString> reposCacheNames; +}; + +class LogCacheData +{ + +protected: + QMutex m_singleDbMutex; + +public: + LogCacheData(){} + ~LogCacheData(){ + if (m_mainDB.hasLocalData()) { + m_mainDB.setLocalData(0L); + } + } + + bool checkReposDb(QDataBase aDb) + { +#if QT_VERSION < 0x040000 + if (!aDb) { + return false; + } + if (!aDb->open()) { + return false; + } +#else + if (!aDb.open()) { + return false; + } +#endif + + QSqlQuery _q(QString::null, aDb); +#if QT_VERSION < 0x040000 + QStringList list = aDb->tables(); +#else + QStringList list = aDb.tables(); +#endif + +#if QT_VERSION < 0x040000 + if (list.find("logentries")==list.end()) { + aDb->transaction(); +#else + if (list.indexOf("logentries")==-1) { + aDb.transaction(); +#endif + _q.exec("CREATE TABLE \"logentries\" (\"revision\" INTEGER UNIQUE,\"date\" INTEGER,\"author\" TEXT, \"message\" TEXT)"); +#if QT_VERSION < 0x040000 + aDb->commit(); +#else + aDb.commit(); +#endif + } +#if QT_VERSION < 0x040000 + if (list.find("changeditems")==list.end()) { + aDb->transaction(); +#else + if (list.indexOf("changeditems")==-1) { + aDb.transaction(); +#endif + _q.exec("CREATE TABLE \"changeditems\" (\"revision\" INTEGER,\"changeditem\" TEXT,\"action\" TEXT,\"copyfrom\" TEXT,\"copyfromrev\" INTEGER, PRIMARY KEY(revision,changeditem,action))"); +#if QT_VERSION < 0x040000 + aDb->commit(); +#else + aDb.commit(); +#endif + } +#if QT_VERSION < 0x040000 + list = aDb->tables(); + if (list.find("logentries")==list.end() || list.find("changeditems")==list.end()) { +#else + list = aDb.tables(); + if (list.indexOf("logentries")==-1 || list.indexOf("changeditems")==-1) { +#endif + return false; + } + return true; + } + + QString createReposDB(const svn::Path&reposroot) { + QMutexLocker locker( &m_singleDbMutex ); + + QDataBase _mdb = getMainDB(); + + QSqlQuery query1(QString::null,_mdb); + QString q("insert into "+QString(SQLMAINTABLE)+" (reposroot) VALUES('"+reposroot+"')"); +#if QT_VERSION < 0x040000 + _mdb->transaction(); +#else + _mdb.transaction(); +#endif + + query1.exec(q); +#if QT_VERSION < 0x040000 + _mdb->commit(); +#else + _mdb.commit(); +#endif + QSqlQuery query(QString::null,_mdb); + query.prepare(s_reposSelect); + query.bindValue(0,reposroot.native()); + query.exec(); + QString db; +#if QT_VERSION < 0x040000 + if (query.lastError().type()==QSqlError::None && query.next()) { +#else + if (query.lastError().type()==QSqlError::NoError && query.next()) { +#endif + db = query.value(0).toString(); + } + else { + qDebug("Error select_01: %s (%s)",query.lastError().text().TOUTF8().data(), + query.lastQuery().TOUTF8().data()); + } + if (!db.isEmpty()) { + QString fulldb = m_BasePath+"/"+db+".db"; + QDataBase _db = QSqlDatabase::addDatabase(SQLTYPE,"tmpdb"); +#if QT_VERSION < 0x040000 + _db->setDatabaseName(fulldb); +#else + _db.setDatabaseName(fulldb); +#endif + if (!checkReposDb(_db)) { + } + QSqlDatabase::removeDatabase("tmpdb"); + } + return db; + } + + QDataBase getReposDB(const svn::Path&reposroot) { +#if QT_VERSION < 0x040000 + if (!getMainDB()) { + return 0; +#else + if (!getMainDB().isValid()) { + return QDataBase(); +#endif + } + bool checkDone = false; + // make sure path is correct eg. without traling slashes. + QString dbFile; + QSqlQuery c(QString::null,getMainDB()); + c.prepare(s_reposSelect); + c.bindValue(0,reposroot.native()); + c.exec(); + +#if QT_VERSION < 0x040000 + //qDebug("Check for path: "+reposroot.native()); +#endif + + // only the first one + if ( c.next() ) { +#if QT_VERSION < 0x040000 +/* qDebug( c.value(0).toString() + ": " + + c.value(0).toString() );*/ +#endif + dbFile = c.value(0).toString(); + } + if (dbFile.isEmpty()) { + dbFile = createReposDB(reposroot); + if (dbFile.isEmpty()) { +#if QT_VERSION < 0x040000 + return 0; +#else + return QSqlDatabase(); +#endif + } + checkDone=true; + } + if (m_mainDB.localData()->reposCacheNames.find(dbFile)!=m_mainDB.localData()->reposCacheNames.end()) { + return QSqlDatabase::database(m_mainDB.localData()->reposCacheNames[dbFile]); + } + int i = 0; + QString _key = dbFile; + while (QSqlDatabase::contains(_key)) { + _key = QString("%1-%2").arg(dbFile).arg(i++); + } +// qDebug("The repository key is now: %s",_key.TOUTF8().data()); + QDataBase _db = QSqlDatabase::addDatabase(SQLTYPE,_key); +#if QT_VERSION < 0x040000 + if (!_db) { + return 0; + } +#endif + QString fulldb = m_BasePath+"/"+dbFile+".db"; +#if QT_VERSION < 0x040000 + _db->setDatabaseName(fulldb); +#else + _db.setDatabaseName(fulldb); +#endif +// qDebug("try database open %s",fulldb.TOUTF8().data()); + if (!checkReposDb(_db)) { + qDebug("no DB opened"); +#if QT_VERSION < 0x040000 + _db = 0; +#else + _db = QSqlDatabase(); +#endif + } else { + qDebug("Insert into map"); + m_mainDB.localData()->reposCacheNames[dbFile]=_key; + } + return _db; + } + + QDataBase getMainDB()const + { + if (!m_mainDB.hasLocalData()) { + unsigned i=0; + QString _key = SQLMAIN; + while (QSqlDatabase::contains(_key)) { + _key.sprintf("%s-%i",SQLMAIN,i++); + } + qDebug("The key is now: %s",_key.TOUTF8().data()); + + QDataBase db = QSqlDatabase::addDatabase(SQLTYPE,_key); +#if QT_VERSION < 0x040000 + db->setDatabaseName(m_BasePath+"/maindb.db"); + if (!db->open()) { +#else + db.setDatabaseName(m_BasePath+"/maindb.db"); + if (!db.open()) { +#endif +#if QT_VERSION < 0x040000 + qWarning("Failed to open main database: " + db->lastError().text()); +#endif + } else { + m_mainDB.setLocalData(new ThreadDBStore); + m_mainDB.localData()->key = _key; + m_mainDB.localData()->m_DB = db; + } + } + if (m_mainDB.hasLocalData()) { + return m_mainDB.localData()->m_DB; + } else { +#if QT_VERSION < 0x040000 + return 0; +#else + return QSqlDatabase(); +#endif + } + } + QString m_BasePath; + + mutable QThreadStorage<ThreadDBStore*> m_mainDB; + + static const QString s_reposSelect; +}; + + +QString LogCache::s_CACHE_FOLDER="logcache"; +const QString LogCacheData::s_reposSelect=QString("SELECT id from ")+QString(SQLMAINTABLE)+QString(" where reposroot=? ORDER by id DESC"); + +/*! + \fn svn::cache::LogCache::LogCache() + */ +LogCache::LogCache() +{ + m_BasePath = QDir::HOMEDIR()+"/.svnqt"; + setupCachePath(); +} + +LogCache::LogCache(const QString&aBasePath) +{ + if (mSelf) { + delete mSelf; + } + mSelf=this; + if (aBasePath.isEmpty()) { + m_BasePath=QDir::HOMEDIR()+"/.svnqt"; + } else { + m_BasePath=aBasePath; + } + setupCachePath(); +} + + +LogCache::~LogCache() +{ +} + +/*! + \fn svn::cache::LogCache::setupCachePath() + */ +void LogCache::setupCachePath() +{ + m_CacheData = new LogCacheData; + m_CacheData->m_BasePath=m_BasePath; + QDir d; + if (!d.exists(m_BasePath)) { + d.mkdir(m_BasePath); + } + m_BasePath=m_BasePath+"/"+s_CACHE_FOLDER; + if (!d.exists(m_BasePath)) { + d.mkdir(m_BasePath); + } + m_CacheData->m_BasePath=m_BasePath; + if (d.exists(m_BasePath)) { + setupMainDb(); + } +} + +void LogCache::setupMainDb() +{ +#ifndef NO_SQLITE3 + if (!QSqlDatabase::isDriverAvailable(SQLTYPE)) { + QSqlDatabase::registerSqlDriver(SQLTYPE,new QSqlDriverCreator<QSQLite3Driver>); + } +#endif + QDataBase mainDB = m_CacheData->getMainDB(); +#if QT_VERSION < 0x040000 + if (!mainDB || !mainDB->open()) { + qWarning("Failed to open main database: " + (mainDB?mainDB->lastError().text():"No database object.")); +#else + if (!mainDB.isValid()) { + qWarning("Failed to open main database."); +#endif + } else { + QSqlQuery q(QString::null, mainDB); +#if QT_VERSION < 0x040000 + mainDB->transaction(); +#else + mainDB.transaction(); +#endif + if (!q.exec("CREATE TABLE IF NOT EXISTS \""+QString(SQLMAINTABLE)+"\" (\"reposroot\" TEXT,\"id\" INTEGER PRIMARY KEY NOT NULL);")) { +#if QT_VERSION < 0x040000 + qWarning("Failed create main database: " + mainDB->lastError().text()); +#endif + } +#if QT_VERSION < 0x040000 + mainDB->commit(); +#else + mainDB.commit(); +#endif + } +} + +} +} + + +/*! + \fn svn::cache::LogCache::self() + */ +svn::cache::LogCache* svn::cache::LogCache::self() +{ + if (!mSelf) { + mSelf=new LogCache(); + } + return mSelf; +} + + +/*! + \fn svn::cache::LogCache::reposDb() + */ +QDataBase svn::cache::LogCache::reposDb(const QString&aRepository) +{ +// qDebug("reposDB"); + return m_CacheData->getReposDB(aRepository); +} + + +/*! + \fn svn::cache::LogCache::cachedRepositories()const + */ +QStringList svn::cache::LogCache::cachedRepositories()const +{ + static QString s_q(QString("select \"reposroot\" from ")+QString(SQLMAINTABLE)+QString("order by reposroot")); + QDataBase mainDB = m_CacheData->getMainDB(); + QStringList _res; +#if QT_VERSION < 0x040000 + if (!mainDB || !mainDB->open()) { +#else + if (!mainDB.isValid()) { +#endif + qWarning("Failed to open main database."); + return _res; + } + QSqlQuery cur(QString::null,mainDB); + cur.prepare(s_q); + if (!cur.exec()) { + qDebug(cur.lastError().text().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not retrieve values: ")+cur.lastError().text()); + return _res; + } + while (cur.next()) { + _res.append(cur.value(0).toString()); + } + + return _res; +} + +bool svn::cache::LogCache::valid()const +{ + QDataBase mainDB = m_CacheData->getMainDB(); +#if QT_VERSION < 0x040000 + if (!mainDB || !mainDB->open()) { +#else + if (!mainDB.isValid()) { +#endif + return false; + } + return true; +} diff --git a/src/svnqt/cache/LogCache.hpp b/src/svnqt/cache/LogCache.hpp new file mode 100644 index 0000000..9e76697 --- /dev/null +++ b/src/svnqt/cache/LogCache.hpp @@ -0,0 +1,41 @@ +#ifndef _LOG_CACHE_HPP +#define _LOG_CACHE_HPP + +#include <qstring.h> +#include <qdir.h> + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/shared_pointer.hpp" + +namespace svn { + namespace cache { + + class LogCacheData; + + class SVNQT_EXPORT LogCache + { + private: + svn::SharedPointer<LogCacheData> m_CacheData; + + protected: + LogCache(); + static LogCache* mSelf; + QString m_BasePath; + static QString s_CACHE_FOLDER; + void setupCachePath(); + void setupMainDb(); + + public: + ///! should used for testing only! + LogCache(const QString&aBasePath); + virtual ~LogCache(); + static LogCache* self(); + QDataBase reposDb(const QString&aRepository); + QStringList cachedRepositories()const; + + bool valid()const; + }; + } +} + +#endif diff --git a/src/svnqt/cache/ReposLog.cpp b/src/svnqt/cache/ReposLog.cpp new file mode 100644 index 0000000..89be2d0 --- /dev/null +++ b/src/svnqt/cache/ReposLog.cpp @@ -0,0 +1,535 @@ +#include "ReposLog.hpp" + +#include "LogCache.hpp" +#include "svnqt/info_entry.hpp" +#include "svnqt/svnqttypes.hpp" +#include "svnqt/client.hpp" +#include "svnqt/context_listener.hpp" +#include "svnqt/cache/DatabaseException.hpp" + +#include <qsqldatabase.h> + +#if QT_VERSION < 0x040000 +#else +#include <QSqlError> +#include <QSqlQuery> +#include <QVariant> +#define Q_LLONG qlonglong +#endif + +/*! + \fn svn::cache::ReposLog::ReposLog(svn::Client*aClient,const QString&) + */ +svn::cache::ReposLog::ReposLog(svn::Client*aClient,const QString&aRepository) + :m_Client(), +#if QT_VERSION < 0x040000 + m_Database(0), +#else + m_Database(), +#endif + m_ReposRoot(aRepository),m_latestHead(svn::Revision::UNDEFINED) +{ + m_Client=aClient; + ContextP ctx = m_Client->getContext(); + if (!aRepository.isEmpty()) { + m_Database = LogCache::self()->reposDb(aRepository); + } +} + + +/*! + \fn svn::cache::ReposLog::latestHeadRev() + */ +svn::Revision svn::cache::ReposLog::latestHeadRev() +{ + if (!m_Client||m_ReposRoot.isEmpty()) { + return svn::Revision::UNDEFINED; + } +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + m_Database = LogCache::self()->reposDb(m_ReposRoot); +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + return svn::Revision::UNDEFINED; + } + } + /// no catch - exception has go trough... + qDebug("Getting headrev"); + svn::InfoEntries e = m_Client->info(m_ReposRoot,svn::DepthEmpty,svn::Revision::HEAD,svn::Revision::HEAD); + if (e.count()<1||e[0].reposRoot().isEmpty()) { + return svn::Revision::UNDEFINED; + } + qDebug("Getting headrev done"); + return e[0].revision(); +} + + +/*! + \fn svn::cache::ReposLog::latestCachedRev() + */ +svn::Revision svn::cache::ReposLog::latestCachedRev() +{ + if (m_ReposRoot.isEmpty()) { + return svn::Revision::UNDEFINED; + } +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + m_Database = LogCache::self()->reposDb(m_ReposRoot); +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + return svn::Revision::UNDEFINED; + } + } + QString q("select revision from 'logentries' order by revision DESC limit 1"); + QSqlQuery _q(QString::null, m_Database); + if (!_q.exec(q)) { + qDebug(_q.lastError().text().TOUTF8().data()); + return svn::Revision::UNDEFINED; + } + int _r; + if (_q.isActive() && _q.next()) { + //qDebug("Sel result: %s",_q.value(0).toString().TOUTF8().data()); + _r = _q.value(0).toInt(); + } else { + qDebug(_q.lastError().text().TOUTF8().data()); + return svn::Revision::UNDEFINED; + } + return _r; +} + +bool svn::cache::ReposLog::checkFill(svn::Revision&start,svn::Revision&end,bool checkHead) +{ +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + m_Database = LogCache::self()->reposDb(m_ReposRoot); +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + return false; + } + } + ContextP cp = m_Client->getContext(); + long long icount=0; + + svn::Revision _latest=latestCachedRev(); +// qDebug("Latest cached rev: %i",_latest.revnum()); +// qDebug("End revision is: %s",end.toString().TOUTF8().data()); + + if (checkHead && _latest.revnum()>=latestHeadRev().revnum()) { + return true; + } + + start=date2numberRev(start); + end=date2numberRev(end); + + // both should now one of START, HEAD or NUMBER + if (start==svn::Revision::HEAD || (end==svn::Revision::NUMBER && start==svn::Revision::NUMBER && start.revnum()>end.revnum())) { + svn::Revision tmp = start; + start = end; + end = tmp; + } + svn::Revision _rstart=_latest.revnum()+1; + svn::Revision _rend = end; + if (_rend==svn::Revision::UNDEFINED) { +// qDebug("Setting end to Head"); + _rend=svn::Revision::HEAD; + } + // no catch - exception should go outside. + if (_rstart==0){ + _rstart = 1; + } +// qDebug("Getting log %s -> %s",_rstart.toString().TOUTF8().data(),_rend.toString().TOUTF8().data()); + if (_rend==svn::Revision::HEAD) { + _rend=latestHeadRev(); + } + + if (_rend==svn::Revision::HEAD||_rend.revnum()>_latest.revnum()) { + LogEntriesMap _internal; +// qDebug("Retrieving from network."); + if (!m_Client->log(m_ReposRoot,_rstart,_rend,_internal,svn::Revision::UNDEFINED,true,false)) { + return false; + } + LogEntriesMap::ConstIterator it=_internal.begin(); + + for (;it!=_internal.end();++it) { + _insertLogEntry((*it)); + if (cp && cp->getListener()) { + //cp->getListener()->contextProgress(++icount,_internal.size()); + if (cp->getListener()->contextCancel()) { + throw DatabaseException(QString("Could not retrieve values: User cancel.")); + } + } + } + } + return true; +} + +bool svn::cache::ReposLog::fillCache(const svn::Revision&_end) +{ + svn::Revision end = _end; + svn::Revision start = latestCachedRev().revnum()+1; + return checkFill(start,end,false); +} + +/*! + \fn svn::cache::ReposLog::simpleLog(const svn::Revision&start,const svn::Revision&end,LogEntriesMap&target) + */ +bool svn::cache::ReposLog::simpleLog(LogEntriesMap&target,const svn::Revision&_start,const svn::Revision&_end,bool noNetwork) +{ + if (!m_Client||m_ReposRoot.isEmpty()) { + return false; + } + target.clear(); + ContextP cp = m_Client->getContext(); + + svn::Revision end = _end; + svn::Revision start = _start; + if (!noNetwork) { + if (!checkFill(start,end,true)) { + return false; + } + } else { + end=date2numberRev(end,noNetwork); + start=date2numberRev(start,noNetwork); + } + + if (end==svn::Revision::HEAD) { + end = latestCachedRev(); + } + if (start==svn::Revision::HEAD) { + start=latestCachedRev(); + } + static QString sCount("select count(*) from logentries where revision<=? and revision>=?"); + static QString sEntry("select revision,author,date,message from logentries where revision<=? and revision>=?"); + static QString sItems("select changeditem,action,copyfrom,copyfromrev from changeditems where revision=?"); + + QSqlQuery bcount(QString::null,m_Database); + bcount.prepare(sCount); + + QSqlQuery bcur(QString::null,m_Database); + bcur.prepare(sEntry); + + QSqlQuery cur(QString::null,m_Database); + cur.prepare(sItems); + + bcount.bindValue(0,Q_LLONG(end.revnum())); + bcount.bindValue(1,Q_LLONG(start.revnum())); + if (!bcount.exec()) { + qDebug(bcount.lastError().text().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not retrieve count: ")+bcount.lastError().text()); + return false; + } + bcount.next(); + if (bcount.value(0).toLongLong()<1) { + // we didn't found logs with this parameters + return false; + } + + bcur.bindValue(0,Q_LLONG(end.revnum())); + bcur.bindValue(1,Q_LLONG(start.revnum())); + + if (!bcur.exec()) { + qDebug(bcur.lastError().text().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not retrieve values: ")+bcur.lastError().text()); + return false; + } + Q_LLONG revision; + while(bcur.next()) { + revision = bcur.value(0).toLongLong(); + cur.bindValue(0,revision); + if (!cur.exec()) { + qDebug(cur.lastError().text().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not retrieve values: ")+cur.lastError().text() + ,cur.lastError().number()); + return false; + } + target[revision].revision=revision; + target[revision].author=bcur.value(1).toString(); + target[revision].date=bcur.value(2).toLongLong(); + target[revision].message=bcur.value(3).toString(); + while(cur.next()) { + LogChangePathEntry lcp; + QString ac = cur.value(1).toString(); +#if QT_VERSION < 0x040000 + lcp.action=ac[0].latin1(); +#else + lcp.action=ac[0].toLatin1(); +#endif + lcp.copyFromPath=cur.value(2).toString(); + lcp.path= cur.value(0).toString(); + lcp.copyFromRevision=cur.value(3).toLongLong(); + target[revision].changedPaths.push_back(lcp); + } + if (cp && cp->getListener()) { + if (cp->getListener()->contextCancel()) { + throw svn::cache::DatabaseException(QString("Could not retrieve values: User cancel.")); + return false; + } + } + } + return true; +} + + +/*! + \fn svn::cache::ReposLog::date2numberRev(const svn::Revision&) + */ +svn::Revision svn::cache::ReposLog::date2numberRev(const svn::Revision&aRev,bool noNetwork) +{ + if (aRev!=svn::Revision::DATE) { + return aRev; + } +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + return svn::Revision::UNDEFINED; + } + static QString _q("select revision from logentries where date<? order by revision desc"); + QSqlQuery query("select revision,date from logentries order by revision desc limit 1",m_Database); + +#if QT_VERSION < 0x040000 + if (query.lastError().type()!=QSqlError::None) { +#else + if (query.lastError().type()!=QSqlError::NoError) { +#endif + qDebug(query.lastError().text().TOUTF8().data()); + } + bool must_remote=!noNetwork; + if (query.next()) { + if (query.value(1).toLongLong()>=aRev.date()) { + must_remote=false; + } + } + if (must_remote) { + svn::InfoEntries e = (m_Client->info(m_ReposRoot,svn::DepthEmpty,aRev,aRev));; + if (e.count()<1||e[0].reposRoot().isEmpty()) { + return aRev; + } + return e[0].revision(); + } + query.prepare(_q); + query.bindValue(0,Q_LLONG(aRev.date())); + query.exec(); +#if QT_VERSION < 0x040000 + if (query.lastError().type()!=QSqlError::None) { +#else + if (query.lastError().type()!=QSqlError::NoError) { +#endif + qDebug(query.lastError().text().TOUTF8().data()); + } + if (query.next()) { + return query.value(0).toInt(); + } + // not found... + if (noNetwork) { + return svn::Revision::UNDEFINED; + } + svn::InfoEntries e = (m_Client->info(m_ReposRoot,svn::DepthEmpty,svn::Revision::HEAD,svn::Revision::HEAD));; + if (e.count()<1||e[0].reposRoot().isEmpty()) { + return svn::Revision::UNDEFINED; + } + return e[0].revision(); +} + + +/*! + \fn svn::cache::ReposLog::insertLogEntry(const svn::LogEntry&) + */ +bool svn::cache::ReposLog::_insertLogEntry(const svn::LogEntry&aEntry) +{ + QSqlRecord *buffer; + +#if QT_VERSION < 0x040000 + m_Database->transaction(); + Q_LLONG j = aEntry.revision; +#else + m_Database.transaction(); + qlonglong j = aEntry.revision; +#endif + static QString qEntry("insert into logentries (revision,date,author,message) values (?,?,?,?)"); + static QString qPathes("insert into changeditems (revision,changeditem,action,copyfrom,copyfromrev) values (?,?,?,?,?)"); + QSqlQuery _q(QString::null,m_Database); + _q.prepare(qEntry); + _q.bindValue(0,j); + _q.bindValue(1,aEntry.date); + _q.bindValue(2,aEntry.author); + _q.bindValue(3,aEntry.message); + if (!_q.exec()) { +#if QT_VERSION < 0x040000 + m_Database->rollback(); +#else + m_Database.rollback(); +#endif + qDebug("Could not insert values: %s",_q.lastError().text().TOUTF8().data()); + qDebug(_q.lastQuery().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not insert values: ")+_q.lastError().text(),_q.lastError().number()); + } + _q.prepare(qPathes); + svn::LogChangePathEntries::ConstIterator cpit = aEntry.changedPaths.begin(); + for (;cpit!=aEntry.changedPaths.end();++cpit){ + _q.bindValue(0,j); + _q.bindValue(1,(*cpit).path); + _q.bindValue(2,QString(QChar((*cpit).action))); + _q.bindValue(3,(*cpit).copyFromPath); + _q.bindValue(4,Q_LLONG((*cpit).copyFromRevision)); + if (!_q.exec()) { +#if QT_VERSION < 0x040000 + m_Database->rollback(); +#else + m_Database.rollback(); +#endif + qDebug("Could not insert values: %s",_q.lastError().text().TOUTF8().data()); + qDebug(_q.lastQuery().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not insert values: ")+_q.lastError().text(),_q.lastError().number()); + } + } +#if QT_VERSION < 0x040000 + m_Database->commit(); +#else + m_Database.commit(); +#endif + return true; +} + +bool svn::cache::ReposLog::insertLogEntry(const svn::LogEntry&aEntry) +{ + return _insertLogEntry(aEntry); +} + + +/*! + \fn svn::cache::ReposLog::log(const svn::Path&,const svn::Revision&start, const svn::Revision&end,const svn::Revision&peg,svn::LogEntriesMap&target, bool strictNodeHistory,int limit)) + */ +bool svn::cache::ReposLog::log(const svn::Path&what,const svn::Revision&_start, const svn::Revision&_end,const svn::Revision&_peg,svn::LogEntriesMap&target, bool strictNodeHistory,int limit) +{ + static QString s_q("select logentries.revision,logentries.author,logentries.date,logentries.message from logentries where logentries.revision in (select changeditems.revision from changeditems where (changeditems.changeditem='%1' or changeditems.changeditem GLOB '%2/*') %3 GROUP BY changeditems.revision) ORDER BY logentries.revision DESC"); + + static QString s_e("select changeditem,action,copyfrom,copyfromrev from changeditems where changeditems.revision='%1'"); + + svn::Revision peg = date2numberRev(_peg,true); + svn::Revision end = date2numberRev(_end,true); + svn::Revision start = date2numberRev(_start,true); + QString query_string = QString(s_q).arg(what.native()).arg(what.native()).arg((peg==svn::Revision::UNDEFINED?"":QString(" AND revision<=%1").arg(peg.revnum()))); + if (peg==svn::Revision::UNDEFINED) { + peg = latestCachedRev(); + } + if (!itemExists(peg,what)) { + throw svn::cache::DatabaseException(QString("Entry '%1' does not exists at revision %2").arg(what.native()).arg(peg.toString())); + } + if (limit>0) { + query_string+=QString(" LIMIT %1").arg(limit); + } + QSqlQuery _q(QString::null,m_Database); + QSqlQuery _q2(QString::null,m_Database); + _q.prepare(query_string); + if (!_q.exec()) { + qDebug("Could not select values: %s",_q.lastError().text().TOUTF8().data()); + qDebug(_q.lastQuery().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not select values: ")+_q.lastError().text(),_q.lastError().number()); + } + while(_q.next()) { + Q_LLONG revision = _q.value(0).toLongLong(); + target[revision].revision=revision; + target[revision].author=_q.value(1).toString(); + target[revision].date=_q.value(2).toLongLong(); + target[revision].message=_q.value(3).toString(); + query_string=s_e.arg(revision); + _q2.prepare(query_string); + if (!_q2.exec()) { + qDebug("Could not select values: %s",_q2.lastError().text().TOUTF8().data()); + } else { + while (_q2.next()) { +#if QT_VERSION < 0x040000 + target[revision].changedPaths.push_back ( + LogChangePathEntry (_q2.value(0).toString(), + _q2.value(1).toString()[0], + _q2.value(2).toString(), + _q2.value(3).toLongLong() + ) + ); +#else + target[revision].changedPaths.push_back ( + LogChangePathEntry (_q2.value(0).toString(), + _q2.value(1).toChar().toLatin1(), + _q2.value(2).toString(), + _q2.value(3).toLongLong() + ) + ); +#endif + } + } + + } + return true; +} + + +/*! + \fn svn::cache::ReposLog::itemExists(const svn::Revision&,const QString&) + */ +bool svn::cache::ReposLog::itemExists(const svn::Revision&peg,const svn::Path&path) +{ + /// @todo this moment I have no idea how to check real with all moves and deletes of parent folders without a hell of sql statements so we make it quite simple: it exists if we found it. + + +#if 0 + static QString _s1("select revision from changeditems where changeditem='%1' and action='A' and revision<=%2 order by revision desc limit 1"); + QSqlQuery _q(QString::null,m_Database); + QString query_string=QString(_s1).arg(path.native()).arg(peg.revnum()); + if (!_q.exec(query_string)) { + qDebug("Could not select values: %s",_q.lastError().text().TOUTF8().data()); + qDebug(_q.lastQuery().TOUTF8().data()); + throw svn::cache::DatabaseException(QString("Could not select values: ")+_q.lastError().text(),_q.lastError().number()); + } + qDebug(_q.lastQuery().TOUTF8().data()); + + + svn::Path _p = path; + static QString _s2("select revision from changeditem where changeditem in (%1) and action='D' and revision>%2 and revision<=%3 order by revision desc limit 1"); + QStringList p_list; + while (_p.length()>0) { + p_list.append(QString("'%1'").arg(_p.native())); + _p.removeLast(); + } + query_string=QString(_s2).arg(p_list.join(",")).arg(); +#endif + return true; +} + +bool svn::cache::ReposLog::isValid()const +{ +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + m_Database = LogCache::self()->reposDb(m_ReposRoot); +#if QT_VERSION < 0x040000 + if (!m_Database) { +#else + if (!m_Database.isValid()) { +#endif + return false; + } + } + return true; +} diff --git a/src/svnqt/cache/ReposLog.hpp b/src/svnqt/cache/ReposLog.hpp new file mode 100644 index 0000000..e81a5c9 --- /dev/null +++ b/src/svnqt/cache/ReposLog.hpp @@ -0,0 +1,70 @@ +#ifndef _REPOS_LOG_HPP +#define _REPOS_LOG_HPP + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" +#include "svnqt/revision.hpp" + +#include <qsqldatabase.h> +#include <qstring.h> + +namespace svn +{ + +class Client; + +namespace cache +{ + +class SVNQT_EXPORT ReposLog +{ +protected: + svn::Client*m_Client; + mutable QDataBase m_Database; + QString m_ReposRoot; + svn::Revision m_latestHead; + //! internal insert. + bool _insertLogEntry(const svn::LogEntry&); + bool checkFill(svn::Revision&_start,svn::Revision&_end,bool checkHead); + +public: + ReposLog(svn::Client*aClient,const QString&aRepository=QString::null); + + QString ReposRoot() const + { + return m_ReposRoot; + } + + QDataBase Database() const + { + return m_Database; + } + //! search for latest head revision on network for assigned repository + svn::Revision latestHeadRev(); + //! return lates revision in cache + svn::Revision latestCachedRev(); + //! simple retrieves logentries + /*! + * This method acts on network, too for checking if there are new entries on server. + * + * @param target where to store the result + * @param start revision to start for search + * @param end revision to end for search + * @param noNetwork if yes, no check on network for newer revisions will made + * @return true if entries found and no error, if no entries found false + * @exception svn::DatabaseException in case of errors + */ + bool simpleLog(LogEntriesMap&target,const svn::Revision&start,const svn::Revision&end,bool noNetwork=false); + svn::Revision date2numberRev(const svn::Revision&,bool noNetwork=false); + bool fillCache(const svn::Revision&end); + bool insertLogEntry(const svn::LogEntry&); + bool log(const svn::Path&,const svn::Revision&start, const svn::Revision&end,const svn::Revision&peg,svn::LogEntriesMap&target, bool strictNodeHistory,int limit); + bool itemExists(const svn::Revision&,const svn::Path&); + + bool isValid()const; +}; + +} +} + +#endif diff --git a/src/svnqt/cache/sqlite3/README b/src/svnqt/cache/sqlite3/README new file mode 100644 index 0000000..e2f7914 --- /dev/null +++ b/src/svnqt/cache/sqlite3/README @@ -0,0 +1,32 @@ +With this driver you can access the files created by sqlite3 through +the standard Qt sql module. The driver name is QSQLITE3. + +Although there are many other solutions to access such DB files, I think +that using this driver has some advantages: + +--> You use the standard Qt interface so you can reuse exinting code or + switch to or from other DB types quite easily. + +--> Soft transition to Qt 4: Qt 4 supports sqlite3, you can prepare your + application now. + +--> The source of this driver is smaller than any other, you can incorporate + it on your application with little overhead and without requiring external + libraries. + + +Developer note: + +The driver is a merge between the QSQLITE driver in Qt 3 and in Qt 4 beta 1, with +small tweaks, so I think is quite stable and usable. +Please report success or failure, thanks + +To compile + +qmake +make +cp sqldrivers/libqsqlite3.so $QTDIR/plugins/sqldrivers (probably as root) + +use it as any other Qt sql driver. + +Have fun, Stefano !!!
\ No newline at end of file diff --git a/src/svnqt/cache/sqlite3/qsql_sqlite3.cpp b/src/svnqt/cache/sqlite3/qsql_sqlite3.cpp new file mode 100644 index 0000000..93010c1 --- /dev/null +++ b/src/svnqt/cache/sqlite3/qsql_sqlite3.cpp @@ -0,0 +1,485 @@ +/**************************************************************************** +** +** Implementation of SQLite driver classes. +** +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt GUI Toolkit. +** EDITIONS: FREE, ENTERPRISE +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "qsql_sqlite3.h" + +#include <qdatetime.h> +#include <qvaluevector.h> +#include <qregexp.h> +#include <qfile.h> +#include <sqlite3.h> + +#if (QT_VERSION-0 < 0x030200) +# include <qvector.h> +# if !defined Q_WS_WIN32 +# include <unistd.h> +# endif +#else +# include <qptrvector.h> +# if !defined Q_WS_WIN32 +# include <unistd.h> +# endif +#endif + +typedef struct sqlite3_stmt sqlite3_stmt; + +#define QSQLITE3_DRIVER_NAME "QSQLITE3" + +static QVariant::Type qSqliteType(int tp) +{ + switch (tp) { + case SQLITE_INTEGER: + return QVariant::Int; + case SQLITE_FLOAT: + return QVariant::Double; + case SQLITE_BLOB: + return QVariant::ByteArray; + case SQLITE_TEXT: + default: + return QVariant::String; + } +} + +static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::Type type, + int errorCode = -1) +{ + return QSqlError(descr, + QString::fromUtf8(sqlite3_errmsg(access)), + type, errorCode); +} + +class QSQLite3DriverPrivate +{ +public: + QSQLite3DriverPrivate(); + sqlite3 *access; + bool utf8; +}; + +QSQLite3DriverPrivate::QSQLite3DriverPrivate() : access(0) +{ + utf8 = true; +} + +class QSQLite3ResultPrivate +{ +public: + QSQLite3ResultPrivate(QSQLite3Result *res); + void cleanup(); + bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch); + bool isSelect(); + // initializes the recordInfo and the cache + void initColumns(); + void finalize(); + + QSQLite3Result* q; + sqlite3 *access; + + sqlite3_stmt *stmt; + + uint skippedStatus: 1; // the status of the fetchNext() that's skipped + uint skipRow: 1; // skip the next fetchNext()? + uint utf8: 1; + QSqlRecord rInf; +}; + +static const uint initial_cache_size = 128; + +QSQLite3ResultPrivate::QSQLite3ResultPrivate(QSQLite3Result* res) : q(res), access(0), + stmt(0), skippedStatus(false), skipRow(false), utf8(false) +{ +} + +void QSQLite3ResultPrivate::cleanup() +{ + finalize(); + rInf.clear(); + skippedStatus = false; + skipRow = false; + q->setAt(QSql::BeforeFirst); + q->setActive(false); + q->cleanup(); +} + +void QSQLite3ResultPrivate::finalize() +{ + if (!stmt) + return; + + sqlite3_finalize(stmt); + stmt = 0; +} + +// called on first fetch +void QSQLite3ResultPrivate::initColumns() +{ + rInf.clear(); + + int nCols = sqlite3_column_count(stmt); + if (nCols <= 0) + return; + + q->init(nCols); + + for (int i = 0; i < nCols; ++i) { + QString colName = QString::fromUtf8(sqlite3_column_name(stmt, i)); + + int dotIdx = colName.findRev('.'); + rInf.append(QSqlField(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), + qSqliteType(sqlite3_column_type(stmt, i)))); + } +} + +bool QSQLite3ResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch) +{ + int res; + unsigned int i; + + if (skipRow) { + // already fetched + Q_ASSERT(!initialFetch); + skipRow = false; + return skippedStatus; + } + skipRow = initialFetch; + + if (!stmt) + return false; + + // keep trying while busy, wish I could implement this better. + while ((res = sqlite3_step(stmt)) == SQLITE_BUSY) { + // sleep instead requesting result again immidiately. +#if defined Q_OS_WIN + Sleep(1000); +#else + sleep(1); +#endif + } + + switch(res) { + case SQLITE_ROW: + // check to see if should fill out columns + if (rInf.isEmpty()) + // must be first call. + initColumns(); + if (idx < 0 && !initialFetch) + return true; + for (i = 0; i < rInf.count(); ++i) + // todo - handle other types + values[i + idx] = QString::fromUtf8((char *)(sqlite3_column_text(stmt, i))); + // values[i + idx] = utf8 ? QString::fromUtf8(fvals[i]) : QString::fromAscii(fvals[i]); + return true; + case SQLITE_DONE: + if (rInf.isEmpty()) + // must be first call. + initColumns(); + q->setAt(QSql::AfterLast); + return false; + case SQLITE_ERROR: + case SQLITE_MISUSE: + default: + // something wrong, don't get col info, but still return false + q->setLastError(qMakeError(access, "Unable to fetch row", QSqlError::Connection, res)); + finalize(); + q->setAt(QSql::AfterLast); + return false; + } + return false; +} + +QSQLite3Result::QSQLite3Result(const QSQLite3Driver* db) + : QSqlCachedResult(db) +{ + d = new QSQLite3ResultPrivate(this); + d->access = db->d->access; +} + +QSQLite3Result::~QSQLite3Result() +{ + d->cleanup(); + delete d; +} + +/* + Execute \a query. +*/ +bool QSQLite3Result::reset (const QString &query) +{ + // this is where we build a query. + if (!driver() || !driver()->isOpen() || driver()->isOpenError()) + return false; + + d->cleanup(); + + setSelect(false); + + int res = sqlite3_prepare(d->access, query.utf8().data(), (query.length() + 1) * sizeof(QChar), + &d->stmt, 0); + + if (res != SQLITE_OK) { + setLastError(qMakeError(d->access, "Unable to execute statement", QSqlError::Statement, res)); + d->finalize(); + return false; + } + + d->skippedStatus = d->fetchNext(cache(), 0, true); + + setSelect(!d->rInf.isEmpty()); + setActive(true); + return true; +} + +bool QSQLite3Result::gotoNext(QSqlCachedResult::ValueCache& row, int idx) +{ + return d->fetchNext(row, idx, false); +} + +int QSQLite3Result::size() +{ + return -1; +} + +int QSQLite3Result::numRowsAffected() +{ + return sqlite3_changes(d->access); +} + +///////////////////////////////////////////////////////// + +QSQLite3Driver::QSQLite3Driver(QObject * parent, const char *name) + : QSqlDriver(parent, name) +{ + d = new QSQLite3DriverPrivate(); +} + +QSQLite3Driver::QSQLite3Driver(sqlite3 *connection, QObject *parent, const char *name) + : QSqlDriver(parent, name) +{ + d = new QSQLite3DriverPrivate(); + d->access = connection; + setOpen(true); + setOpenError(false); +} + + +QSQLite3Driver::~QSQLite3Driver() +{ + delete d; +} + +bool QSQLite3Driver::hasFeature(DriverFeature f) const +{ + switch (f) { + case Transactions: + case Unicode: + case BLOB: + return true; + default: + break; + } + return false; +} + +/* + SQLite dbs have no user name, passwords, hosts or ports. + just file names. +*/ +bool QSQLite3Driver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &) +{ + if (isOpen()) + close(); + + if (db.isEmpty()) + return false; + + if (sqlite3_open(QFile::encodeName(db), &d->access) == SQLITE_OK) { + setOpen(true); + setOpenError(false); + return true; + } else { + setLastError(qMakeError(d->access, "Error opening database", + QSqlError::Connection)); + setOpenError(true); + return false; + } +} + +void QSQLite3Driver::close() +{ + if (isOpen()) { + if (sqlite3_close(d->access) != SQLITE_OK) + setLastError(qMakeError(d->access, "Error closing database", + QSqlError::Connection)); + d->access = 0; + setOpen(false); + setOpenError(false); + } +} + +QSqlQuery QSQLite3Driver::createQuery() const +{ + return QSqlQuery(new QSQLite3Result(this)); +} + +bool QSQLite3Driver::beginTransaction() +{ + if (!isOpen() || isOpenError()) + return false; + + QSqlQuery q(createQuery()); + if (!q.exec("BEGIN")) { + setLastError(QSqlError("Unable to begin transaction", + q.lastError().databaseText(), QSqlError::Transaction)); + return false; + } + + return true; +} + +bool QSQLite3Driver::commitTransaction() +{ + if (!isOpen() || isOpenError()) + return false; + + QSqlQuery q(createQuery()); + if (!q.exec("COMMIT")) { + setLastError(QSqlError("Unable to begin transaction", + q.lastError().databaseText(), QSqlError::Transaction)); + return false; + } + + return true; +} + +bool QSQLite3Driver::rollbackTransaction() +{ + if (!isOpen() || isOpenError()) + return false; + + QSqlQuery q(createQuery()); + if (!q.exec("ROLLBACK")) { + setLastError(QSqlError("Unable to begin transaction", + q.lastError().databaseText(), QSqlError::Transaction)); + return false; + } + + return true; +} + +QStringList QSQLite3Driver::tables(const QString &typeName) const +{ + QStringList res; + if (!isOpen()) + return res; + int type = typeName.toInt(); + + QSqlQuery q = createQuery(); + q.setForwardOnly(TRUE); +#if (QT_VERSION-0 >= 0x030200) + if ((type & (int)QSql::Tables) && (type & (int)QSql::Views)) + q.exec("SELECT name FROM sqlite_master WHERE type='table' OR type='view'"); + else if (typeName.isEmpty() || (type & (int)QSql::Tables)) + q.exec("SELECT name FROM sqlite_master WHERE type='table'"); + else if (type & (int)QSql::Views) + q.exec("SELECT name FROM sqlite_master WHERE type='view'"); +#else + q.exec("SELECT name FROM sqlite_master WHERE type='table' OR type='view'"); +#endif + + + if (q.isActive()) { + while(q.next()) + res.append(q.value(0).toString()); + } + +#if (QT_VERSION-0 >= 0x030200) + if (type & (int)QSql::SystemTables) { + // there are no internal tables beside this one: + res.append("sqlite_master"); + } +#endif + + return res; +} + +QSqlIndex QSQLite3Driver::primaryIndex(const QString &tblname) const +{ + QSqlRecordInfo rec(recordInfo(tblname)); // expensive :( + + if (!isOpen()) + return QSqlIndex(); + + QSqlQuery q = createQuery(); + q.setForwardOnly(TRUE); + // finrst find a UNIQUE INDEX + q.exec("PRAGMA index_list('" + tblname + "');"); + QString indexname; + while(q.next()) { + if (q.value(2).toInt()==1) { + indexname = q.value(1).toString(); + break; + } + } + if (indexname.isEmpty()) + return QSqlIndex(); + + q.exec("PRAGMA index_info('" + indexname + "');"); + + QSqlIndex index(indexname); + while(q.next()) { + QString name = q.value(2).toString(); + QSqlVariant::Type type = QSqlVariant::Invalid; + if (rec.contains(name)) + type = rec.find(name).type(); + index.append(QSqlField(name, type)); + } + return index; +} + +QSqlRecordInfo QSQLite3Driver::recordInfo(const QString &tbl) const +{ + if (!isOpen()) + return QSqlRecordInfo(); + + QSqlQuery q = createQuery(); + q.setForwardOnly(TRUE); + q.exec("SELECT * FROM " + tbl + " LIMIT 1"); + return recordInfo(q); +} + +QSqlRecord QSQLite3Driver::record(const QString &tblname) const +{ + if (!isOpen()) + return QSqlRecord(); + + return recordInfo(tblname).toRecord(); +} + +QSqlRecord QSQLite3Driver::record(const QSqlQuery& query) const +{ + if (query.isActive() && query.driver() == this) { + QSQLite3Result* result = (QSQLite3Result*)query.result(); + return result->d->rInf; + } + return QSqlRecord(); +} + +QSqlRecordInfo QSQLite3Driver::recordInfo(const QSqlQuery& query) const +{ + if (query.isActive() && query.driver() == this) { + QSQLite3Result* result = (QSQLite3Result*)query.result(); + return QSqlRecordInfo(result->d->rInf); + } + return QSqlRecordInfo(); +} diff --git a/src/svnqt/cache/sqlite3/qsql_sqlite3.h b/src/svnqt/cache/sqlite3/qsql_sqlite3.h new file mode 100644 index 0000000..f89c038 --- /dev/null +++ b/src/svnqt/cache/sqlite3/qsql_sqlite3.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Definition of SQLite driver classes. +** +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt GUI Toolkit. +** EDITIONS: FREE, ENTERPRISE +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QSQL_SQLITE3_H +#define QSQL_SQLITE3_H + +#include <qsqldriver.h> +#include <qsqlresult.h> +#include <qsqlrecord.h> +#include <qsqlindex.h> +#include "qsqlcachedresult.h" + +#if (QT_VERSION-0 >= 0x030200) +typedef QVariant QSqlVariant; +#endif + +#if defined (Q_OS_WIN32) +# include <qt_windows.h> +#endif + +class QSQLite3DriverPrivate; +class QSQLite3ResultPrivate; +class QSQLite3Driver; +struct sqlite3; + +class QSQLite3Result : public QSqlCachedResult +{ + friend class QSQLite3Driver; + friend class QSQLite3ResultPrivate; +public: + QSQLite3Result(const QSQLite3Driver* db); + ~QSQLite3Result(); + +protected: + bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); + bool reset (const QString& query); + int size(); + int numRowsAffected(); + +private: + QSQLite3ResultPrivate* d; +}; + +class QSQLite3Driver : public QSqlDriver +{ + friend class QSQLite3Result; +public: + QSQLite3Driver(QObject *parent = 0, const char *name = 0); + QSQLite3Driver(sqlite3 *connection, QObject *parent = 0, const char *name = 0); + ~QSQLite3Driver(); + bool hasFeature(DriverFeature f) const; + bool open(const QString & db, + const QString & user, + const QString & password, + const QString & host, + int port, + const QString & connOpts); + bool open( const QString & db, + const QString & user, + const QString & password, + const QString & host, + int port ) { return open (db, user, password, host, port, QString()); } + void close(); + QSqlQuery createQuery() const; + bool beginTransaction(); + bool commitTransaction(); + bool rollbackTransaction(); + QStringList tables(const QString &user) const; + + QSqlRecord record(const QString& tablename) const; + QSqlRecordInfo recordInfo(const QString& tablename) const; + QSqlIndex primaryIndex(const QString &table) const; + QSqlRecord record(const QSqlQuery& query) const; + QSqlRecordInfo recordInfo(const QSqlQuery& query) const; + +private: + QSQLite3DriverPrivate* d; +}; +#endif diff --git a/src/svnqt/cache/sqlite3/qsqlcachedresult.cpp b/src/svnqt/cache/sqlite3/qsqlcachedresult.cpp new file mode 100644 index 0000000..8a23183 --- /dev/null +++ b/src/svnqt/cache/sqlite3/qsqlcachedresult.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2005 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "qsqlcachedresult.h" + +#include <qvariant.h> +#include <qdatetime.h> +#include <qvaluevector.h> + +static const uint initial_cache_size = 128; + +class QSqlCachedResultPrivate +{ +public: + QSqlCachedResultPrivate(); + bool canSeek(int i) const; + inline int cacheCount() const; + void init(int count, bool fo); + void cleanup(); + int nextIndex(); + void revertLast(); + + QSqlCachedResult::ValueCache cache; + int rowCacheEnd; + int colCount; + bool forwardOnly; +}; + +QSqlCachedResultPrivate::QSqlCachedResultPrivate(): + rowCacheEnd(0), colCount(0), forwardOnly(false) +{ +} + +void QSqlCachedResultPrivate::cleanup() +{ + cache.clear(); + forwardOnly = false; + colCount = 0; + rowCacheEnd = 0; +} + +void QSqlCachedResultPrivate::init(int count, bool fo) +{ + Q_ASSERT(count); + cleanup(); + forwardOnly = fo; + colCount = count; + if (fo) { + cache.resize(count); + rowCacheEnd = count; + } else { + cache.resize(initial_cache_size * count); + } +} + +int QSqlCachedResultPrivate::nextIndex() +{ + if (forwardOnly) + return 0; + int newIdx = rowCacheEnd; + if (rowCacheEnd == (int)cache.size()) + cache.resize(cache.size() * 2); +/* if (newIdx + colCount > cache.size()){ + if(cache.size() * 2 < cache.size() + 10000) + cache.resize(cache.size() * 2); + else + cache.resize(cache.size() + 10000); + }*/ + rowCacheEnd += colCount; + + return newIdx; +} + +bool QSqlCachedResultPrivate::canSeek(int i) const +{ + if (forwardOnly || i < 0) + return false; + return rowCacheEnd >= (i + 1) * colCount; +} + +void QSqlCachedResultPrivate::revertLast() +{ + if (forwardOnly) + return; + rowCacheEnd -= colCount; +} + +inline int QSqlCachedResultPrivate::cacheCount() const +{ + Q_ASSERT(!forwardOnly); + Q_ASSERT(colCount); + return rowCacheEnd / colCount; +} + +////////////// + +QSqlCachedResult::QSqlCachedResult(const QSqlDriver * db): QSqlResult (db) +{ + d = new QSqlCachedResultPrivate(); +} + +QSqlCachedResult::~QSqlCachedResult() +{ + delete d; +} + +void QSqlCachedResult::init(int colCount) +{ + d->init(colCount, isForwardOnly()); +} + +bool QSqlCachedResult::fetch(int i) +{ + if ((!isActive()) || (i < 0)) + return false; + if (at() == i) + return true; + if (d->forwardOnly) { + // speed hack - do not copy values if not needed + if (at() > i || at() == QSql::AfterLast) + return false; + while(at() < i - 1) { + if (!gotoNext(d->cache, -1)) + return false; + setAt(at() + 1); + } + if (!gotoNext(d->cache, 0)) + return false; + setAt(at() + 1); + return true; + } + if (d->canSeek(i)) { + setAt(i); + return true; + } + if (d->rowCacheEnd > 0) + setAt(d->cacheCount()-1); + while (at() < i) { + if (!cacheNext()) + return false; + } + return true; +} + +bool QSqlCachedResult::fetchNext() +{ + if (d->canSeek(at() + 1)) { + setAt(at() + 1); + return true; + } + return cacheNext(); +} + +bool QSqlCachedResult::fetchPrevious() +{ + return fetch(at() - 1); +} + +bool QSqlCachedResult::fetchFirst() +{ + if (d->forwardOnly && at() != QSql::BeforeFirst) { + return false; + } + if (d->canSeek(0)) { + setAt(0); + return true; + } + return cacheNext(); +} + +bool QSqlCachedResult::fetchLast() +{ + if (at() == QSql::AfterLast) { + if (d->forwardOnly) + return false; + else + return fetch(d->cacheCount() - 1); + } + + int i = at(); + while (fetchNext()) + ++i; /* brute force */ + if (d->forwardOnly && at() == QSql::AfterLast) { + setAt(i); + return true; + } else { + return fetch(i); + } +} + +QVariant QSqlCachedResult::data(int i) +{ + int idx = d->forwardOnly ? i : at() * d->colCount + i; + if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) + return QVariant(); + + return d->cache.at(idx); +} + +bool QSqlCachedResult::isNull(int i) +{ + int idx = d->forwardOnly ? i : at() * d->colCount + i; + if (i > d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) + return true; + + return d->cache.at(idx).isNull(); +} + +void QSqlCachedResult::cleanup() +{ + setAt(QSql::BeforeFirst); + setActive(false); + d->cleanup(); +} + +bool QSqlCachedResult::cacheNext() +{ + if (!gotoNext(d->cache, d->nextIndex())) { + d->revertLast(); + return false; + } + setAt(at() + 1); + return true; +} + +int QSqlCachedResult::colCount() const +{ + return d->colCount; +} + +QSqlCachedResult::ValueCache &QSqlCachedResult::cache() +{ + return d->cache; +} + diff --git a/src/svnqt/cache/sqlite3/qsqlcachedresult.h b/src/svnqt/cache/sqlite3/qsqlcachedresult.h new file mode 100644 index 0000000..fa8924f --- /dev/null +++ b/src/svnqt/cache/sqlite3/qsqlcachedresult.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2005 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QSQLCACHEDRESULT_P_H +#define QSQLCACHEDRESULT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qsqlresult.h> + +class QVariant; +template <typename T> class QValueVector; + +class QSqlCachedResultPrivate; + +class QM_EXPORT_SQL QSqlCachedResult: public QSqlResult +{ +public: + virtual ~QSqlCachedResult(); + + typedef QValueVector<QVariant> ValueCache; + +protected: + QSqlCachedResult(const QSqlDriver * db); + + void init(int colCount); + void cleanup(); + + virtual bool gotoNext(ValueCache &values, int index) = 0; + + QVariant data(int i); + bool isNull(int i); + bool fetch(int i); + bool fetchNext(); + bool fetchPrevious(); + bool fetchFirst(); + bool fetchLast(); + + int colCount() const; + ValueCache &cache(); + +private: + bool cacheNext(); + QSqlCachedResultPrivate *d; +}; + +#endif // QSQLCACHEDRESULT_P_H diff --git a/src/svnqt/cache/test/CMakeLists.txt b/src/svnqt/cache/test/CMakeLists.txt new file mode 100644 index 0000000..ecc6130 --- /dev/null +++ b/src/svnqt/cache/test/CMakeLists.txt @@ -0,0 +1,19 @@ +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +MACRO(BUILD_TEST tname) + SET(${tname}-src ${tname}.cpp) + IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${tname}.h) + SET(${tname}-src ${${tname}-src} ${tname}.h) + ENDIF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${tname}.h) + ADD_EXECUTABLE(${tname} ${${tname}-src}) + TARGET_LINK_LIBRARIES(${tname} ${svnqt-name} ${QT_LIBRARIES}) + ADD_TEST(${tname} ${CMAKE_CURRENT_BINARY_DIR}/${tname}) +ENDMACRO(BUILD_TEST) + +IF (BUILD_TESTS) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/testconfig.h.in + ${CMAKE_CURRENT_BINARY_DIR}/testconfig.h + ) + BUILD_TEST(sqlite) +ENDIF(BUILD_TESTS) diff --git a/src/svnqt/cache/test/sqlite.cpp b/src/svnqt/cache/test/sqlite.cpp new file mode 100644 index 0000000..4f14b2d --- /dev/null +++ b/src/svnqt/cache/test/sqlite.cpp @@ -0,0 +1,111 @@ +#include <qsql.h> +#include <qsqldatabase.h> +#include <qstringlist.h> +#include <iostream> +#include <qapplication.h> +#include <qtextstream.h> + +#include "svnqt/client.hpp" +#include "svnqt/svnqttypes.hpp" +#include "svnqt/log_entry.hpp" + +#include "svnqt/cache/LogCache.hpp" +#include "svnqt/cache/ReposLog.hpp" +#include "svnqt/cache/test/testconfig.h" +#include "svnqt/cache/DatabaseException.hpp" + +#if QT_VERSION < 0x040000 +#else +#include <QSqlQuery> +#include <QSqlError> +#endif + +int main(int argc,char**argv) +{ + QApplication app(argc,argv); + + svn::ContextP m_CurrentContext; + svn::Client* m_Svnclient; + m_Svnclient=svn::Client::getobject(0,0); + m_CurrentContext = new svn::Context(); + + m_Svnclient->setContext(m_CurrentContext); + + QStringList list; + QStringList::Iterator it; + // goes into "self" of logcache + new svn::cache::LogCache(TESTDBPATH); + list = QSqlDatabase::drivers(); + it = list.begin(); + while( it != list.end() ) { + std::cout << (*it).TOUTF8().data() << std::endl; + ++it; + } + svn::cache::ReposLog rl(m_Svnclient,"http://www.alwins-world.de/repos/kdesvn"); + QDataBase db = rl.Database(); +#if QT_VERSION < 0x040000 + if (!db) { +#else + if (!db.isValid()) { +#endif + std::cerr << "No database object."<<std::endl; + exit(-1); + } +#if QT_VERSION < 0x040000 + list = db->tables(); +#else + list = db.tables(); +#endif + it = list.begin(); + while( it != list.end() ) { + std::cout << ( *it ).TOUTF8().data() << std::endl; + ++it; + } + svn::LogEntriesMap lm; + try { + rl.simpleLog(lm,100,svn::Revision::HEAD); + } + catch (const svn::cache::DatabaseException&cl) + { + std::cerr << cl.msg().TOUTF8().data() <<std::endl; + } + catch (const svn::Exception&ce) + { + std::cerr << "Exception: " << ce.msg().TOUTF8().data() <<std::endl; + } + svn::LogEntriesMap::ConstIterator lit = lm.begin(); + std::cout<<"Count: "<<lm.count()<<std::endl; + + svn::Revision r("{2006-09-27}"); + std::cout << r.toString().TOUTF8().data() << " -> " << rl.date2numberRev(r).toString().TOUTF8().data()<<std::endl; + r = svn::Revision::HEAD; + std::cout << rl.date2numberRev(r).toString().TOUTF8().data()<<std::endl; + try { + rl.insertLogEntry(lm[100]); + } + catch (const svn::cache::DatabaseException&cl) + { + std::cerr << cl.msg().TOUTF8().data() << std::endl; + } + QSqlQuery q("insert into logentries(revision,date,author,message) values ('100','1122591406','alwin','copy and moving works now in basic form')",db); + q.exec(); + std::cerr << "\n" << q.lastError().text().TOUTF8().data()<<std::endl; + +#if QT_VERSION < 0x040000 +#else + db=QSqlDatabase(); +#endif + try { + rl.log("/trunk/src/svnqt",1,1000,svn::Revision::UNDEFINED,lm,false,-1); + } + catch (const svn::cache::DatabaseException&cl) + { + std::cerr << cl.msg().TOUTF8().data() <<std::endl; + } + catch (const svn::Exception&ce) + { + std::cerr << "Exception: " << ce.msg().TOUTF8().data() <<std::endl; + } + std::cout<<"Count: "<<lm.count()<<std::endl; + return 0; +} diff --git a/src/svnqt/cache/test/testconfig.h.in b/src/svnqt/cache/test/testconfig.h.in new file mode 100644 index 0000000..865ac6e --- /dev/null +++ b/src/svnqt/cache/test/testconfig.h.in @@ -0,0 +1,8 @@ +#ifndef __TEST_CONFIG_H +#define __TEST_CONFIG_H + +#define TESTREPOPATH "@CMAKE_CURRENT_BINARY_DIR@/repo" +#define TESTCOPATH "@CMAKE_CURRENT_BINARY_DIR@/co" +#define TESTDBPATH "@CMAKE_CURRENT_BINARY_DIR@/db" + +#endif diff --git a/src/svnqt/check.hpp b/src/svnqt/check.hpp new file mode 100644 index 0000000..0c6a340 --- /dev/null +++ b/src/svnqt/check.hpp @@ -0,0 +1,50 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_CHECK_HPP_ +#define _SVNCPP_CHECK_HPP_ + +// subversion api +#include "svn_version.h" + +/** + * Check if the current version of the subversion + * API is at least major.minor + */ +#define CHECK_SVN_VERSION (major,minor) \ + (SVN_VER_MAJOR > (major) || \ + (SVN_VER_MAJOR == (major) && SVN_VER_MINOR > (minor)) + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client.cpp b/src/svnqt/client.cpp new file mode 100644 index 0000000..d78c416 --- /dev/null +++ b/src/svnqt/client.cpp @@ -0,0 +1,104 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1550 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif + +// svncpp +#include "svnqt/client.hpp" +#include "svnqt/client_impl.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include "svn_opt.h" + +#include <svn_cmdline.h> + +#include <qstringlist.h> +#include <qdir.h> + +namespace svn +{ + //! this namespace contains only internal stuff not for public use + namespace internal { + //! small helper class + /*! + There will be an static instance created for calling the constructor at program load. + */ + class SvnInit + { + public: + //! constructor calling initialize functions + SvnInit(); + ~SvnInit(){}; + }; + + SvnInit::SvnInit() { + svn_cmdline_init("svnqt",0); + qDebug("svn_cmdline_init done"); + QString BasePath=QDir::HOMEDIR(); + QDir d; + if (!d.exists(BasePath)) { + d.mkdir(BasePath); + } + BasePath=BasePath+"/"+".svnqt"; + if (!d.exists(BasePath)) { + d.mkdir(BasePath); + } + + } + } + + Client::Client() + { + } + + Client::~Client () + { + } + + Client*Client::getobject(ContextP context,int subtype) + { + static internal::SvnInit sInit; + switch(subtype) { + case 0: + return new Client_impl(context); + break; + default: + break; + } + return 0L; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client.hpp b/src/svnqt/client.hpp new file mode 100644 index 0000000..622c0be --- /dev/null +++ b/src/svnqt/client.hpp @@ -0,0 +1,882 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_CLIENT_H_ +#define _SVNCPP_CLIENT_H_ + +// Ignore MSVC 6 compiler warning: debug symbol truncated +#if defined (_MSC_VER) && _MSC_VER <= 1200 +#pragma warning (disable: 4786) +#endif + +// Ignore MSVC 7, 2005 & 2008 compiler warning: C++ exception specification +#if defined (_MSC_VER) && _MSC_VER > 1200 && _MSC_VER <= 1550 +#pragma warning (disable: 4290) +#endif + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" +#include "svnqt/svnstream.hpp" + +// qt +#include <qglobal.h> + +#if QT_VERSION < 0x040000 + #include <qstring.h> + #include <qpair.h> + #include <qvaluelist.h> + #include <qmap.h> +#else + #include <QtCore> +#endif + +// svnqt +#include "svnqt/context.hpp" +#include "svnqt/exception.hpp" +#include "svnqt/path.hpp" +#include "svnqt/entry.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/log_entry.hpp" +#include "svnqt/info_entry.hpp" +#include "svnqt/annotate_line.hpp" +#include "svnqt/stringarray.hpp" +#include "svnqt/diffoptions.hpp" +#include "svnqt/conflictresult.hpp" + +class QStringList; + +namespace svn +{ + /** Subversion client API. + * + * Never use an object of this as global static! This will make problems with subversion + * initialize. + */ + class SVNQT_EXPORT Client + { + public: + + /** + * Initializes the primary memory pool. + */ + Client(); + + virtual ~Client (); + + + /** + * @return returns the Client context + */ + virtual const ContextP + getContext () const = 0; + + /** + * sets the client context + * you have to make sure the old context + * is de-allocated + * + * @param context new context to use + */ + virtual void + setContext (ContextP context) = 0; + + /** + * get a real instance. Result must cleaned with delete. + * \param context The context to use + * \param subtype the wanted implementation - this moment only 0 allowed. + * \return an instance of client or 0L if error. + */ + static Client*getobject(ContextP context,int subtype=0); + + /** + * Enumerates all files/dirs at a given path. + * + * Throws an exception if an error occurs + * + * @param path Path to explore. + * @param descend Recurse into subdirectories if existant. + * @param get_all Return all entries, not just the interesting ones. + * @param update Query the repository for updates. + * @param no_ignore Disregard default and svn:ignore property ignores. + * @param hide_externals don't recurse into external definitions + * @param revision list specific revision when browsing remote, on working copies parameter will ignored + * @param detailed_remote if on remote listing detailed item info should get if possible + * that may slow so should configureable in frontends! + * @return vector with Status entries. + */ + virtual StatusEntries + status (const Path& path, + Depth depth=DepthImmediates, + bool get_all = true, + bool update = false, + bool no_ignore = false, + const Revision revision = svn::Revision::HEAD, + bool detailed_remote = false, + bool hide_externals = false, + const StringArray & changelists=StringArray() ) throw (ClientException) = 0; + + /** + * Returns the status of a single file in the path. + * + * Throws an exception if an error occurs + * + * @param path File to gather status. + * @param update if check against repository if new updates are there (for WC only) + * @param revision list specific revision when browsing remote, on working copies parameter will ignored + * @return a Status with Statis.isVersioned = FALSE + */ + virtual StatusPtr + singleStatus (const Path& path,bool update=false,const Revision revision = svn::Revision::HEAD) throw (ClientException)=0; + + /** + * Executes a revision checkout. + * @param moduleName name of the module to checkout. + * @param destPath destination directory for checkout. + * @param revision the revision number to checkout. If the number is -1 + * then it will checkout the latest revision. + * @param peg Revision to look up + * @param recurse whether you want it to checkout files recursively. + * @param ignore_externals if true don't process externals definitions. + * @exception ClientException + */ + virtual svn_revnum_t + checkout (const Path& moduleName, const Path & destPath, + const Revision & revision, + const Revision & peg = Revision::UNDEFINED, + svn::Depth depth=DepthInfinity, + bool ignore_externals=false, + bool overwrite=false + ) throw (ClientException) = 0; + + /** + * relocate wc @a from to @a to + * @exception ClientException + */ + virtual void + relocate (const Path & path, const QString &from_url, + const QString &to_url, bool recurse) throw (ClientException)=0; + + /** + * Sets a single file for deletion. + * @exception ClientException + */ + virtual svn::Revision + remove (const Path & path, bool force, + bool keep_local = true, + const PropertiesMap&revProps = PropertiesMap()) throw (ClientException)=0; + + /** + * Sets files for deletion. + * + * @param targets targets to delete + * @param force force if files are locally modified + * @exception ClientException + */ + virtual svn::Revision + remove (const Targets & targets, + bool force, + bool keep_local=true, + const PropertiesMap&revProps=PropertiesMap()) throw (ClientException) = 0; + + /** + * Reverts a couple of files to a pristiner state. + * @exception ClientException + */ + virtual void + revert (const Targets & targets, + Depth depth, + const StringArray&changelist=StringArray() + ) throw (ClientException)=0; + + + /** + * Adds a file to the repository. + * @param path the path to add + * @param depth if @a path is a folder add items recursive depending on value if it. + * @param force if true, do not error on already-versioned items. + * @param no_ignore if false don't add files or directories that match ignore patterns. When build against svn 1.2 always false + * @param add_parents if true, go up to the next versioned folder and add all between path and this folder. + * @exception ClientException + */ + virtual void + add (const Path & path, svn::Depth depth,bool force=false, bool no_ignore=false, bool add_parents = true) throw (ClientException)=0; + + /** + * Updates the file or directory. + * @param path targets. + * @param revision the revision number to checkout. + * Revision::HEAD will checkout the + * latest revision. + * @param depth Depthness for operation + * @param ignore_externals ignore externals + * @param allow_unversioned will operation not fail if there are unversioned items in tree with same name. + * @exception ClientException + */ + virtual Revisions + update (const Targets & path, const Revision & revision, + Depth depth,bool ignore_externals,bool allow_unversioned, + bool sticky_depth) throw (ClientException) = 0; + + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param path path of file or directory + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @return contents of the file + */ + virtual QByteArray + cat (const Path & path, + const Revision & revision, + const Revision & peg_revision=svn_opt_revision_unspecified) throw (ClientException)=0; + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param buffer Stream to store content direct + * @param path path of file or directory + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @exception ClientException + */ + virtual void + cat(svn::stream::SvnStream&buffer, + const Path & path, + const Revision & revision, + const Revision & peg_revision) throw (ClientException)=0; + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param path path of file or directory + * @param target new (local) name + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @param peg_revision Revision to look at + */ + virtual void + get (const Path & path, + const QString & target, + const Revision & revision, + const Revision & peg_revision=svn_opt_revision_unspecified) throw (ClientException)=0; + + /** + * Retrieves the contents for a specific @a revision of + * a @a path and stores the result in @a target + * + * @param target the container where to store the result + * @param path path of file or directory + * @param revisionStart revision to retrieve + * @param revisionEnd revision to retrieve + * @param peg indicates in which revision path is valid + */ + virtual void + annotate (AnnotatedFile&target, + const Path & path, + const Revision & revisionStart, + const Revision & revisionEnd, + const Revision & peg = Revision::UNDEFINED, + const DiffOptions&diffoptions = DiffOptions(), + bool ignore_mimetypes = false, + bool include_merged_revisions = false + ) throw (ClientException)=0; + + /** + * Commits changes to the repository. This usually requires + * authentication, see Auth. + * @return Returns revision transferred or svn::Revision::UNDEFINED if the revision number is invalid. + * @param targets files to commit. + * @param message log message. + * @param depth whether the operation should be done recursively. + * @param keep_locks if false unlock items in paths + * @param changelist + * @param keep_changelist + * @exception ClientException + */ + virtual svn::Revision + commit (const Targets & targets, + const QString& message, + svn::Depth depth,bool keep_locks=true, + const svn::StringArray&contents=svn::StringArray(), + const PropertiesMap&revProps=PropertiesMap(), + bool keep_changelist=false + ) throw (ClientException)=0; + + /** + * Copies a versioned file with the history preserved. + * @exception ClientException + */ + virtual svn::Revision + copy (const Path & srcPath, + const Revision & srcRevision, + const Path & destPath) throw (ClientException)=0; + /** + * Copies a versioned file with the history preserved. + * @since subversion 1.5 api + * @see svn_client_copy4 + * @exception ClientException + */ + virtual svn::Revision + copy (const Targets & srcPath, + const Revision & srcRevision, + const Revision & pegRevision, + const Path & destPath, + bool asChild=false,bool makeParent=false,const PropertiesMap&revProps=PropertiesMap()) throw (ClientException)=0; + + /** + * Moves or renames a file. + * @exception ClientException + */ + virtual svn::Revision + move (const Path & srcPath, + const Path & destPath, + bool force) throw (ClientException)=0; + /** + * Moves or renames a file. + * @exception ClientException + */ + virtual svn::Revision + move (const Targets & srcPath, + const Path & destPath, + bool force,bool asChild,bool makeParent,const PropertiesMap&revProps=PropertiesMap()) throw (ClientException)=0; + + /** + * Creates a directory directly in a repository or creates a + * directory on disk and schedules it for addition. If <i>path</i> + * is a URL then authentication is usually required, see Auth and + * the callback asks for a logmessage. With subversion 1.4 the target + * must not exist (\sa svn_client_move4) + * + * @param path + * @param message log message. if it is QString::null asks when working on repository + * @param makeParent create parent folders if not existant (only when build with svn 1.5 or above) + * @exception ClientException + */ + virtual svn::Revision + mkdir (const Path & path, + const QString& message, + bool makeParent=true, + const PropertiesMap&revProps=PropertiesMap() + ) throw (ClientException)=0; + /** + * Creates a directory directly in a repository or creates a + * directory on disk and schedules it for addition. If <i>path</i> + * is a URL then authentication is usually required, see Auth and + * the callback asks for a logmessage. + * + * @param targets encoded pathes to create + * @param message log message. if it is QString::null asks when working on repository + * @param makeParent create parent folders if not existant (only when build with svn 1.5 or above) + * @exception ClientException + */ + virtual svn::Revision + mkdir (const Targets & targets, + const QString& message, + bool makeParent=true, + const PropertiesMap&revProps=PropertiesMap() + ) throw (ClientException)=0; + + /** + * Recursively cleans up a local directory, finishing any + * incomplete operations, removing lockfiles, etc. + * @param path a local directory. + * @exception ClientException + */ + virtual void + cleanup (const Path & path) throw (ClientException)=0; + + /** + * Removes the 'conflicted' state on a file. + * @exception ClientException + */ + virtual void resolve (const Path & path,Depth depth,const ConflictResult&resolution=ConflictResult()) throw (ClientException)=0; + + /** + * Exports the contents of either a subversion repository into a + * 'clean' directory (meaning a directory with no administrative + * directories). + * @exception ClientException + * @param srcPath source path + * @param destPath a destination path that must not already exist. + * @param revision revision to use for the export + * @param peg the revision where the path is first looked up when exporting from a repository. + * @param overwrite overwrite existing files + * @param native_eol Either "LF", "CR" or "CRLF" or NULL. + * @param ignore_externals don't process externals definitions as part of this operation. + * @param recurse if true, export recursively.<br> + Otherwise, export just the directory represented by from and its immediate non-directory children. + */ + virtual svn_revnum_t + doExport (const Path & srcPath, + const Path & destPath, + const Revision & revision, + const Revision & peg = Revision::UNDEFINED, + bool overwrite=false, + const QString&native_eol=QString::null, + bool ignore_externals = false, + svn::Depth depth=svn::DepthInfinity + ) throw (ClientException)=0; + + /** + * Update local copy to mirror a new url. This excapsulates the + * svn_client_switch() client method. + * @exception ClientException + */ + virtual svn_revnum_t + doSwitch ( + const Path & path, const QString& url, + const Revision & revision, + Depth depth, + const Revision & peg=Revision::UNDEFINED, + bool sticky_depth = true, + bool ignore_externals=false, + bool allow_unversioned=false + ) throw (ClientException)=0; + + /** + * Import file or directory PATH into repository directory URL at + * head. This usually requires authentication, see Auth. + * @param path path to import + * @param url + * @param message log message. + * @param depth kind of recurse operation + * @param no_ignore if false, don't add items matching global ignore pattern (@since subversion 1.3) + * @param no_unknown_nodetype if true ignore files type not known like pipes or device files (@since subversion 1.5) + * @exception ClientException + */ + virtual svn::Revision + import (const Path & path, const QString& url, + const QString& message, + svn::Depth depth, + bool no_ignore,bool no_unknown_nodetype, + const PropertiesMap&revProps=PropertiesMap()) throw (ClientException)=0; + + /** + * Merge changes from two paths into a new local path. + * @exception ClientException + */ + virtual void + merge (const Path & path1, const Revision & revision1, + const Path & path2, const Revision & revision2, + const Path & localPath, bool force, + Depth depth, + bool notice_ancestry=false, + bool dry_run=false, + bool record_only=false, + const StringArray&merge_options=StringArray() + ) throw (ClientException)=0; + + virtual void + merge_peg(const Path&src, + const RevisionRanges&ranges, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry=false, + bool dry_run=false, + bool force=false, + bool record_only=false, + const StringArray&merge_options=StringArray() + ) throw (ClientException)=0; + + virtual void + merge_peg(const Path&src, + const RevisionRange&range, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry=false, + bool dry_run=false, + bool force=false, + const StringArray&merge_options=StringArray() + ) throw (ClientException)=0; + + /** + * Retrieve information for the given path + * remote or local. + * + * @param path path for info + * @param rec recursive (if dir) + * @param rev for which revision + * @param peg_revision peg revision + * @return InfoEntries + */ + virtual InfoEntries + info (const Path &path, + Depth depth, + const Revision & rev, + const Revision & peg_revision=svn_opt_revision_unspecified, + const StringArray&changelists=StringArray() + ) throw (ClientException)=0; + + /** + * Retrieve log information for the given path + * Loads the log messages result set. The first + * entry is the youngest revision. + * + * You can use the constants Revision::START and + * Revision::HEAD + * + * @param path + * @param revisionStart + * @param revisionEnd + * @param discoverChangedPaths + * @param strictNodeHistory + * @param limit the maximum log entries count. + * @return a vector with log entries + */ + virtual LogEntriesPtr + log (const Path& path, + const Revision & revisionStart, + const Revision & revisionEnd, + const Revision & revisionPeg, + bool discoverChangedPaths=false, + bool strictNodeHistory=true,int limit = 0, + bool include_merged_revisions = false, + const StringArray&revprops=StringArray() + ) throw (ClientException)=0; + + /** + * Retrieve log information for the given path + * Loads the log messages result set. Result will stored + * in a map where the key is the revision number + * + * You can use the constants Revision::START and + * Revision::HEAD + * + * @param path Path to make a log for + * @param revisionStart + * @param revisionEnd + * @param target the logmap where to store the entries + * @param discoverChangedPaths + * @param strictNodeHistory + * @param limit (ignored when subversion 1.1 API) + * @return true if success + */ + virtual bool + log (const Path& path, const Revision & revisionStart, + const Revision & revisionEnd, + LogEntriesMap&target, + const Revision & revisionPeg=Revision::UNDEFINED, + bool discoverChangedPaths=false, + bool strictNodeHistory=true,int limit = 0, + bool include_merged_revisions = false, + const StringArray&revprops=StringArray() + ) throw (ClientException)=0; + + /** + * Produce diff output which describes the delta between + * @a path/@a revision1 and @a path/@a revision2. @a path + * can be either a working-copy path or a URL. + * + * A ClientException will be thrown if either @a revision1 or + * @a revision2 has an `unspecified' or unrecognized `kind'. + * + * @param tmpPath prefix for a temporary directory needed by diff. + * Filenames will have ".tmp" and similar added to this prefix in + * order to ensure uniqueness. + * @param path path of the file. + * @param revision1 one of the revisions to check. + * @param revision2 the other revision. + * @param recurse whether the operation should be done recursively. + * @param ignoreAncestry whether the files will be checked for + * relatedness. + * @param noDiffDeleted if true, no diff output will be generated on deleted files. + * @param ignore_contenttype if true generate diff even the items are marked as binaries + * @param extra extra options for diff ("-b", "-w","--ignore-eol-style") + * @return delta between the files + * @exception ClientException + */ + virtual QByteArray + diff_peg(const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype, + const StringArray&extra, + const StringArray&changelists + ) throw (ClientException)=0; + + /** + * Same as other diff but extra options always set to empty list. + */ + virtual QByteArray + diff_peg (const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype) throw (ClientException)=0; + + /** + * Produce diff output which describes the delta between + * @a path1/@a revision1 and @a path2/@a revision2. @a path2 + * can be either a working-copy path or a URL. + * + * A ClientException will be thrown if either @a revision1 or + * @a revision2 has an `unspecified' or unrecognized `kind'. + * + * @param tmpPath prefix for a temporary directory needed by diff. + * Filenames will have ".tmp" and similar added to this prefix in + * order to ensure uniqueness. + * @param path1 first file or folder to diff. + * @param path2 second file or folder to diff. + * @param revision1 one of the revisions to check (path1). + * @param revision2 the other revision (path2). + * @param recurse whether the operation should be done recursively. + * @param ignoreAncestry whether the files will be checked for + * relatedness. + * @param noDiffDeleted if true, no diff output will be generated on deleted files. + * @param ignore_contenttype if true generate diff even the items are marked as binaries + * @param extra extra options for diff ("-b", "-w","--ignore-eol-style") + * @return delta between the files + * @exception ClientException + */ + virtual QByteArray + diff (const Path & tmpPath, const Path & path1,const Path & path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype, + const StringArray&extra, + const StringArray&changelists + ) throw (ClientException)=0; + + /** + * Same as other diff but extra options and changelists always set to empty list. + */ + virtual QByteArray + diff (const Path & tmpPath, const Path & path1,const Path & path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype) throw (ClientException)=0; + + /** + * lists entries in @a pathOrUrl no matter whether local or + * repository + * + * If checking for locks is activated, it lists the locks inside repository, not locks inside + * working copy! + * @param pathOrUrl + * @param revision + * @param peg at wich revision path exists + * @param depth @sa depth + * @param retrieve_locks check for REPOSITORY locks while listing. + * @return a vector of directory entries, each with + * a relative path (only filename). In subversion >= 1.4 an entry without a name is returned, too. This + * is the searched directory (done in subversion itself) + */ + virtual DirEntries + list (const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + svn::Depth depth,bool retrieve_locks) throw (ClientException)=0; + + /** + * lists properties in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param peg most case should set to @a revision + * @param recurse + * @return PropertiesList + */ + virtual PathPropertiesMapListPtr + proplist(const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth=DepthEmpty, + const StringArray&changelists=StringArray() + )=0; + + /** + * lists one property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param peg most case should set to @a revision + * @param recurse + * @return PathPropertiesMapList and revision where the properties are taken from (svn 1.5) or undefined revision (prior 1.5) + */ + virtual QPair<QLONG,PathPropertiesMapList> + propget(const QString& propName, + const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth = svn::DepthEmpty, + const StringArray&changelists=StringArray()) = 0; + + /** + * set property in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param propName + * @param propValue + * @param recurse + * @param skip_checks if true skip validity checks + * @return PropertiesList + */ + virtual void + propset(const QString& propName, + const QString& propValue, + const Path &path, + Depth depth=DepthEmpty, + bool skip_checks=false, + const Revision&base_revision=Revision::UNDEFINED, + const StringArray&changelists=StringArray(), + const PropertiesMap&revProps=PropertiesMap() + ) = 0; + + /** + * delete property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param recurse + */ + virtual void + propdel(const QString& propName, + const Path &path, + Depth depth=DepthEmpty, + bool skip_check=false, + const Revision&base_revision=Revision::UNDEFINED, + const StringArray&changelists=StringArray())=0; + + + /** + * lists revision properties in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @return PropertiesList + */ + virtual QPair<QLONG,PropertiesMap> + revproplist(const Path &path, + const Revision &revision)=0; + + /** + * lists one revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @return PropertiesList + */ + virtual QPair<QLONG,QString> + revpropget(const QString& propName, + const Path &path, + const Revision &revision)=0; + + /** + * set revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param propValue + * @param path + * @param revision + * @param force + * @return Revision + */ + virtual QLONG + revpropset(const QString& propName, + const QString& propValue, + const Path &path, + const Revision &revision, + bool force=false)=0; + + /** + * delete revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param force + * @return Revision + */ + virtual QLONG + revpropdel(const QString& propName, + const Path &path, + const Revision &revision, + bool force=false) = 0; + + /** + * lock files in repository or working copy + * @param targets items to be locked + * @param message if non null stored with each lock in repository + * @param steal_lock if true locks in wc will stolen. + * @since subversion 1.2 + */ + virtual void + lock (const Targets & targets, + const QString& message, + bool steal_lock) throw (ClientException)=0; + /** + * unlock files in repository or working copy + * @param targets items to unlock + * @param break_lock ignore any errors + */ + virtual void + unlock (const Targets&targets, + bool break_lock) throw (ClientException)=0; + + virtual void + url2Revision(const QString&revstring, + Revision&start,Revision&end)=0; + virtual void + url2Revision(const QString&revstring, + Revision&start)=0; + + private: + /** + * disallow assignment operator + */ + Client & operator= (const Client &); + /** + * disallow copy constructor + */ + Client (const Client &); + }; + +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_annotate.cpp b/src/svnqt/client_annotate.cpp new file mode 100644 index 0000000..96bc92c --- /dev/null +++ b/src/svnqt/client_annotate.cpp @@ -0,0 +1,142 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif +// svncpp +#include "svnqt/client_impl.hpp" +#include "svnqt/svnqt_defines.hpp" + +// Subversion api +#include "svn_client.h" + + + +namespace svn +{ +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + static svn_error_t * + annotateReceiver(void *baton, + apr_int64_t line_no, + svn_revnum_t revision, + const char *author, + const char *date, + svn_revnum_t merge_revision, + const char *merge_author, + const char *merge_date, + const char *merge_path, + const char *line, + apr_pool_t *) + { + AnnotatedFile * entries = (AnnotatedFile *) baton; + entries->push_back (AnnotateLine(line_no, revision,author, + date,line,merge_revision, + merge_author,merge_date,merge_path)); + return NULL; + } +#else + static svn_error_t * + annotateReceiver(void *baton, + apr_int64_t line_no, + svn_revnum_t revision, + const char *author, + const char *date, + const char *line, + apr_pool_t *) + { + AnnotatedFile * entries = (AnnotatedFile *) baton; + entries->push_back ( + AnnotateLine (line_no, revision, + author?author:"", + date?date:"", + line?line:"")); + + return NULL; + } +#endif + + void + Client_impl::annotate (AnnotatedFile&target,const Path & path, + const Revision & revisionStart, + const Revision & revisionEnd, + const Revision & peg, + const DiffOptions&diffoptions, + bool ignore_mimetypes, + bool include_merged_revisions + ) throw (ClientException) + { + Pool pool; + svn_error_t *error; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_blame4( + path.path().TOUTF8(), + peg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + diffoptions.options(pool), + ignore_mimetypes, + include_merged_revisions, + annotateReceiver, + &target, + *m_context, // client ctx + pool); +#elif ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + Q_UNUSED(include_merged_revisions); + error = svn_client_blame3( + path.path().TOUTF8(), + peg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + diffoptions.options(pool), + ignore_mimetypes, + annotateReceiver, + &target, + *m_context, // client ctx + pool); +#else + Q_UNUSED(include_merged_revisions); + Q_UNUSED(ignore_mimetypes); + Q_UNUSED(diffoptions); + error = svn_client_blame2( + path.path().TOUTF8(), + peg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + annotateReceiver, + &target, + *m_context, // client ctx + pool); +#endif + if (error != NULL) + { + throw ClientException (error); + } + } +} diff --git a/src/svnqt/client_cat.cpp b/src/svnqt/client_cat.cpp new file mode 100644 index 0000000..fb03f46 --- /dev/null +++ b/src/svnqt/client_cat.cpp @@ -0,0 +1,105 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif +// svncpp +#include "client_impl.hpp" + +// Subversion api +#include "svn_client.h" +//#include "svn_io.h" + +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/status.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnstream.hpp" +#include "svnqt/svnfilestream.hpp" + +namespace svn +{ + QByteArray + Client_impl::cat(const Path & path, + const Revision & revision, + const Revision & peg_revision) throw (ClientException) + { + svn::stream::SvnByteStream buffer(*m_context); + svn_error_t * error = internal_cat(path,revision,peg_revision,buffer); + if (error != 0) + throw ClientException (error); + + return buffer.content(); + } + + void + Client_impl::cat(svn::stream::SvnStream&buffer, + const Path & path, + const Revision & revision, + const Revision & peg_revision) throw (ClientException) + { + svn_error_t * error = internal_cat(path,revision,peg_revision,buffer); + if (error != 0) + throw ClientException (error); + } + + void + Client_impl::get (const Path & path, + const QString & target, + const Revision & revision, + const Revision & peg_revision) throw (ClientException) + { + svn::stream::SvnFileOStream buffer(target,*m_context); + svn_error_t * error = internal_cat(path,revision,peg_revision,buffer); + if (error != 0) + throw ClientException (error); + } + + svn_error_t * Client_impl::internal_cat(const Path & path, + const Revision & revision, + const Revision & peg_revision, + svn::stream::SvnStream&buffer) + { + Pool pool; + return svn_client_cat2 (buffer, + path.path().TOUTF8(), + peg_revision.revision (), + revision.revision (), + *m_context, + pool); + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_diff.cpp b/src/svnqt/client_diff.cpp new file mode 100644 index 0000000..4074fa2 --- /dev/null +++ b/src/svnqt/client_diff.cpp @@ -0,0 +1,184 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif +// svncpp +#include "svnqt/client_impl.hpp" + +// Subversion api +#include "svn_client.h" +#include "svn_path.h" + +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/status.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/helper.hpp" +#include "diff_data.hpp" + +#include <qfile.h> +#include <qstringlist.h> + +#include <apr_xlate.h> + +namespace svn +{ + QByteArray + Client_impl::diff_peg (const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, const bool ignoreAncestry, + const bool noDiffDeleted,const bool ignore_contenttype) throw (ClientException) + { + return diff_peg(tmpPath,path,relativeTo, + revision1,revision2,peg_revision, + depth,ignoreAncestry,noDiffDeleted,ignore_contenttype, + StringArray(),StringArray()); + } + + QByteArray + Client_impl::diff_peg (const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, const bool ignoreAncestry, + const bool noDiffDeleted,const bool ignore_contenttype, + const StringArray&extra,const StringArray&changelists) throw (ClientException) + { + Pool pool; + svn_error_t * error; + const apr_array_header_t * options; + + // svn_client_diff needs an options array, even if it is empty + options = extra.array(pool); + DiffData ddata(tmpPath,path,revision1,path,revision2); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + qDebug("pegged diff4 call"); + error = svn_client_diff_peg4( + options, + path.cstr(), + peg_revision,ddata.r1().revision(),ddata.r2().revision(), + relativeTo.length()>0?relativeTo.cstr():QByteArray(0), + internal::DepthToSvn(depth), + ignoreAncestry,noDiffDeleted,ignore_contenttype, + APR_LOCALE_CHARSET, + ddata.outFile(),ddata.errFile(), + changelists.array(pool), + *m_context, + pool + ); +#else + Q_UNUSED(relativeTo); + Q_UNUSED(changelists); + bool recurse = depth==DepthInfinity; + error = svn_client_diff_peg3( + options, + path.cstr(), + peg_revision,ddata.r1().revision(),ddata.r2().revision(), + recurse?1:0,ignoreAncestry,noDiffDeleted,ignore_contenttype, + APR_LOCALE_CHARSET, + ddata.outFile(),ddata.errFile(), + *m_context, + pool + ); +#endif + if (error != NULL) + { + throw ClientException (error); + } + return ddata.content(); + } + + QByteArray + Client_impl::diff (const Path & tmpPath, const Path & path1,const Path&path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, const bool ignoreAncestry, + const bool noDiffDeleted,const bool ignore_contenttype) throw (ClientException) + { + return diff(tmpPath,path1,path2,relativeTo, + revision1,revision2, + depth,ignoreAncestry,noDiffDeleted,ignore_contenttype, + StringArray(),StringArray()); + } + + QByteArray + Client_impl::diff (const Path & tmpPath, const Path & path1,const Path&path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, const bool ignoreAncestry, + const bool noDiffDeleted,const bool ignore_contenttype, + const StringArray&extra,const StringArray&changelists) throw (ClientException) + { + + Pool pool; + svn_error_t * error; + const apr_array_header_t * options; + + // svn_client_diff needs an options array, even if it is empty + options = extra.array(pool); + DiffData ddata(tmpPath,path1,revision1,path2,revision2); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_diff4(options, + path1.cstr (), ddata.r1().revision (), + path2.cstr (), ddata.r2().revision (), + relativeTo.length()>0?relativeTo.cstr():QByteArray(0), + internal::DepthToSvn(depth), ignoreAncestry, noDiffDeleted, ignore_contenttype, + APR_LOCALE_CHARSET, + ddata.outFile(),ddata.errFile(), + changelists.array(pool), + *m_context, + pool); +#else + Q_UNUSED(changelists); + Q_UNUSED(relativeTo); + bool recurse = depth==DepthInfinity; + // run diff + error = svn_client_diff3 (options, + path1.cstr (), ddata.r1().revision (), + path2.cstr (), ddata.r2().revision (), + recurse?1:0, ignoreAncestry, noDiffDeleted, ignore_contenttype, + APR_LOCALE_CHARSET, + ddata.outFile(),ddata.errFile(), + *m_context, + pool); +#endif + if (error != NULL) + { + throw ClientException (error); + } + return ddata.content(); + + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_impl.cpp b/src/svnqt/client_impl.cpp new file mode 100644 index 0000000..74c2850 --- /dev/null +++ b/src/svnqt/client_impl.cpp @@ -0,0 +1,123 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif + +// svncpp +#include "svnqt/client_impl.hpp" +#include "svn_opt.h" +#include "svnqt/svnqt_defines.hpp" + +#include <qmap.h> +#include <qstringlist.h> +namespace svn +{ + + Client_impl::Client_impl (ContextP context) + : Client() + { + setContext (context); + } + + Client_impl::~Client_impl () + { + } + + const ContextP + Client_impl::getContext () const + { + return m_context; + } + + void + Client_impl::setContext (ContextP context) + { + m_context = context; + } + + + void + Client_impl::url2Revision(const QString&revstring, + Revision&start,Revision&end) + { + Pool pool; + int n = svn_opt_parse_revision(start,end,revstring.TOUTF8(),pool); + + if (n<0) { + start = Revision::UNDEFINED; + end = Revision::UNDEFINED; + } + } + + void Client_impl::url2Revision(const QString&revstring,Revision&start) + { + if (revstring=="WORKING") { + start = Revision::WORKING; + } else if (revstring=="BASE"){ + start = Revision::BASE; + } else if (revstring=="START"){ + start = Revision::START; + } else { + Revision end; + url2Revision(revstring,start,end); + } + } + + apr_hash_t * Client_impl::map2hash(const PropertiesMap&aMap,const Pool&pool) + { + if (aMap.count()==0) { + return 0; + } + apr_hash_t * hash = apr_hash_make(pool); + PropertiesMap::ConstIterator it; + const char*propval; + const char*propname; + QByteArray s,n; + for (it=aMap.begin();it!=aMap.end();++it) { +#if QT_VERSION < 0x040000 + s=it.data().TOUTF8(); +#else + s=it.value().TOUTF8(); +#endif + n=it.key().TOUTF8(); + propval=apr_pstrndup(pool,s,s.size()); + propname=apr_pstrndup(pool,n,n.size()); + apr_hash_set(hash,propname,APR_HASH_KEY_STRING,propval); + } + return hash; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_impl.hpp b/src/svnqt/client_impl.hpp new file mode 100644 index 0000000..4c3b363 --- /dev/null +++ b/src/svnqt/client_impl.hpp @@ -0,0 +1,881 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_CLIENT_IMPL_H_ +#define _SVNCPP_CLIENT_IMPL_H_ + +#include "svnqt/client.hpp" +#include "svnqt/svnqt_defines.hpp" + +// Ignore MSVC 6 compiler warning: debug symbol truncated +#if defined (_MSC_VER) && _MSC_VER <= 1200 +#pragma warning (disable: 4786) +#endif + +// Ignore MSVC 7, 2005 & 2008 compiler warning: C++ exception specification +#if defined (_MSC_VER) && _MSC_VER > 1200 && _MSC_VER <= 1550 +#pragma warning (disable: 4290) +#endif + +class QStringList; + +namespace svn +{ + namespace stream { + class SvnStream; + } + + /** + * Subversion client API. + */ + class SVNQT_NOEXPORT Client_impl:public Client + { + public: + /** + * Initializes the primary memory pool. + */ + Client_impl(ContextP context); + + virtual ~Client_impl(); + + /** + * @return returns the Client context + */ + virtual const ContextP + getContext () const; + + /** + * sets the client context + * you have to make sure the old context + * is de-allocated + * + * @param context new context to use + */ + virtual void + setContext (ContextP context); + + + /** + * Enumerates all files/dirs at a given path. + * + * Throws an exception if an error occurs + * + * @param path Path to explore. + * @param descend Recurse into subdirectories if existant. + * @param get_all Return all entries, not just the interesting ones. + * @param update Query the repository for updates. + * @param no_ignore Disregard default and svn:ignore property ignores. + * @param hide_externals don't recurse into external definitions + * @param revision list specific revision when browsing remote, on working copies parameter will ignored + * @param detailed_remote if on remote listing detailed item info should get if possible + * that may slow so should configureable in frontends! + * @return vector with Status entries. + */ + virtual StatusEntries + status (const Path& path, + Depth depth=DepthEmpty, + bool get_all = true, + bool update = false, + bool no_ignore = false, + const Revision revision = svn::Revision::HEAD, + bool detailed_remote = false, + bool hide_externals = false, + const StringArray & changelists=StringArray()) throw (ClientException); + + /** + * Returns the status of a single file in the path. + * + * Throws an exception if an error occurs + * + * @param path File to gather status. + * @param update if check against repository if new updates are there (for WC only) + * @param revision list specific revision when browsing remote, on working copies parameter will ignored + * @return a Status with Statis.isVersioned = FALSE + */ + virtual StatusPtr + singleStatus (const Path& path,bool update=false,const Revision revision = svn::Revision::HEAD) throw (ClientException); + + /** + * Executes a revision checkout. + * @param moduleName name of the module to checkout. + * @param destPath destination directory for checkout. + * @param revision the revision number to checkout. If the number is -1 + * then it will checkout the latest revision. + * @param peg Revision to look up + * @param recurse whether you want it to checkout files recursively. + * @param ignore_externals if true don't process externals definitions. + * @exception ClientException + */ + virtual svn_revnum_t + checkout (const Path& moduleName, const Path & destPath, + const Revision & revision, + const Revision & peg = Revision::UNDEFINED, + svn::Depth depth=DepthInfinity, + bool ignore_externals=false, + bool overwrite=false + ) throw (ClientException); + + /** + * relocate wc @a from to @a to + * @exception ClientException + */ + virtual void + relocate (const Path & path, const QString &from_url, + const QString &to_url, bool recurse) throw (ClientException); + + /** + * Sets a single file for deletion. + * @exception ClientException + */ + virtual svn::Revision + remove (const Path & path, bool force, + bool keep_local = true, + const PropertiesMap&revProps = PropertiesMap()) throw (ClientException); + + /** + * Sets files for deletion. + * + * @param targets targets to delete + * @param force force if files are locally modified + * @exception ClientException + */ + virtual svn::Revision + remove (const Targets & targets, + bool force, + bool keep_local = true, + const PropertiesMap&revProps = PropertiesMap()) throw (ClientException); + + /** + * Reverts a couple of files to a pristiner state. + * @exception ClientException + */ + virtual void + revert (const Targets & targets, + Depth depth, + const StringArray&changelist=StringArray() + ) throw (ClientException); + + + /** + * Adds a file to the repository. + * @param path the path to add + * @param depth if @a path is a folder add items recursive depending on value if it. Pre-subversion 1.5 DepthInfinity is mapped to recursive, all other to not-recursive. + * @param force if true, do not error on already-versioned items. + * @param no_ignore if false don't add files or directories that match ignore patterns. + * @param add_parents if true, go up to the next versioned folder and add all between path and this folder. Used only with subversion 1.5 or newer + * @exception ClientException + * @sa svn::Depth + */ + virtual void add (const Path & path, svn::Depth depth,bool force=false, bool no_ignore=false, bool add_parents = true) throw (ClientException); + + /** + * Updates the file or directory. + * @param path targets. + * @param revision the revision number to checkout. + * Revision::HEAD will checkout the + * latest revision. + * @param depth Depthness for operation + * @param ignore_externals ignore externals + * @param allow_unversioned will operation not fail if there are unversioned items in tree with same name. + * @exception ClientException + */ + virtual Revisions + update (const Targets & path, const Revision & revision, + Depth depth,bool ignore_externals,bool allow_unversioned, + bool sticky_depth) throw (ClientException); + + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param path path of file or directory + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @param peg_revision Revision to look at + * @return contents of the file + */ + virtual QByteArray + cat (const Path & path, + const Revision & revision, + const Revision & peg_revision=svn_opt_revision_unspecified) throw (ClientException); + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param buffer Stream to store content direct + * @param path path of file or directory + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @exception ClientException + */ + virtual void + cat(svn::stream::SvnStream&buffer, + const Path & path, + const Revision & revision, + const Revision & peg_revision) throw (ClientException); + + /** + * Retrieves the contents for a specific @a revision of + * a @a path at @a peg_revision + * + * @param path path of file or directory + * @param target new (local) name + * @param peg_revision revision to base the URL + * @param revision revision to retrieve + * @param peg_revision Revision to look at + */ + virtual void + get (const Path & path, + const QString & target, + const Revision & revision, + const Revision & peg_revision=svn_opt_revision_unspecified) throw (ClientException); + + /** + * Retrieves the contents for a specific @a revision of + * a @a path and stores the result in @a target + * + * @param target the container where to store the result + * @param path path of file or directory + * @param revisionStart revision to retrieve + * @param revisionEnd revision to retrieve + * @param peg indicates in which revision path is valid + */ + virtual void + annotate (AnnotatedFile&target, + const Path & path, + const Revision & revisionStart, + const Revision & revisionEnd, + const Revision & peg = Revision::UNDEFINED, + const DiffOptions&diffoptions = DiffOptions(), + bool ignore_mimetypes = false, + bool include_merged_revisions = false + ) throw (ClientException); + + /** + * Commits changes to the repository. This usually requires + * authentication, see Auth. + * @return Returns revision transferred or svn::Revision::UNDEFINED if the revision number is invalid. + * @param targets files to commit. + * @param message log message. + * @param depth whether the operation should be done recursively. + * @param keep_locks if false unlock items in paths + * @param changelist + * @param keep_changelist + * @exception ClientException + */ + virtual svn::Revision + commit (const Targets & targets, + const QString& message, + svn::Depth depth,bool keep_locks=true, + const svn::StringArray&changelist=svn::StringArray(), + const PropertiesMap&revProps=PropertiesMap(), + bool keep_changelist=false + ) throw (ClientException); + + /** + * Copies a versioned file with the history preserved. + * @exception ClientException + */ + virtual svn::Revision + copy (const Path & srcPath, + const Revision & srcRevision, + const Path & destPath) throw (ClientException); + /** + * Copies a versioned file with the history preserved. + * @since subversion 1.5 api + * @see svn_client_copy4 + * @exception ClientException + */ + virtual svn::Revision + copy (const Targets & srcPath, + const Revision & srcRevision, + const Revision & pegRevision, + const Path & destPath, + bool asChild=false,bool makeParent=false,const PropertiesMap&revProps=PropertiesMap()) throw (ClientException); + + /** + * Moves or renames a file. + * @exception ClientException + */ + virtual svn::Revision + move (const Path & srcPath, + const Path & destPath, + bool force) throw (ClientException); + + /** + * Moves or renames a file. + * @exception ClientException + */ + virtual svn::Revision + move (const Targets & srcPath, + const Path & destPath, + bool force,bool asChild,bool makeParent,const PropertiesMap&revProps=PropertiesMap()) throw (ClientException); + + /** + * Creates a directory directly in a repository or creates a + * directory on disk and schedules it for addition. If <i>path</i> + * is a URL then authentication is usually required, see Auth and + * the callback asks for a logmessage. + * + * @param path + * @param message log message. if it is QString::null asks when working on repository + * @exception ClientException + */ + virtual svn::Revision + mkdir (const Path & path, + const QString& message, + bool makeParent=true, + const PropertiesMap&revProps=PropertiesMap() + ) throw (ClientException); + /** + * Creates a directory directly in a repository or creates a + * directory on disk and schedules it for addition. If <i>path</i> + * is a URL then authentication is usually required, see Auth and + * the callback asks for a logmessage. + * + * @param targets encoded pathes to create + * @param message log message. if it is QString::null asks when working on repository + * @exception ClientException + */ + virtual svn::Revision + mkdir (const Targets & targets, + const QString& message, + bool makeParent=true, + const PropertiesMap&revProps=PropertiesMap() + ) throw (ClientException); + + /** + * Recursively cleans up a local directory, finishing any + * incomplete operations, removing lockfiles, etc. + * @param path a local directory. + * @exception ClientException + */ + virtual void + cleanup (const Path & path) throw (ClientException); + + /** + * Removes the 'conflicted' state on a file. + * @exception ClientException + */ + virtual void resolve (const Path & path,Depth depth,const ConflictResult&resolution=ConflictResult()) throw (ClientException); + + /** + * Exports the contents of either a subversion repository into a + * 'clean' directory (meaning a directory with no administrative + * directories). + * @exception ClientException + * @param srcPath source path + * @param destPath a destination path that must not already exist. + * @param revision revision to use for the export + * @param peg the revision where the path is first looked up when exporting from a repository. + * @param overwrite overwrite existing files + * @param native_eol Either "LF", "CR" or "CRLF" or NULL. + * @param ignore_externals don't process externals definitions as part of this operation. + * @param recurse if true, export recursively. Otherwise, export just the directory represented by from and its immediate non-directory children. + */ + virtual svn_revnum_t + doExport (const Path & srcPath, + const Path & destPath, + const Revision & revision, + const Revision & peg = Revision::UNDEFINED, + bool overwrite=false, + const QString&native_eol=QString::null, + bool ignore_externals = false, + svn::Depth depth=svn::DepthInfinity + ) throw (ClientException); + + /** + * Update local copy to mirror a new url. This excapsulates the + * svn_client_switch() client method. + * @exception ClientException + */ + virtual svn_revnum_t + doSwitch ( + const Path & path, const QString& url, + const Revision & revision, + Depth depth, + const Revision & peg=Revision::UNDEFINED, + bool sticky_depth = true, + bool ignore_externals=false, + bool allow_unversioned=false + ) throw (ClientException); + + /** + * Import file or directory PATH into repository directory URL at + * head. This usually requires authentication, see Auth. + * @param path path to import + * @param url + * @param message log message. + * @param depth kind of recurse operation + * @param no_ignore if false, don't add items matching global ignore pattern + * @param no_unknown_nodetype if true ignore files type not known like pipes or device files + * @exception ClientException + */ + virtual svn::Revision + import (const Path & path, const QString& url, + const QString& message, + svn::Depth depth, + bool no_ignore,bool no_unknown_nodetype, + const PropertiesMap&revProps=PropertiesMap()) throw (ClientException); + + /** + * Merge changes from two paths into a new local path. + * @exception ClientException + */ + virtual void + merge (const Path & path1, const Revision & revision1, + const Path & path2, const Revision & revision2, + const Path & localPath, bool force, + Depth depth, + bool notice_ancestry=false, + bool dry_run=false, + bool record_only=false, + const StringArray&merge_options=StringArray() + ) throw (ClientException); + + virtual void + merge_peg(const Path&src, + const RevisionRanges&ranges, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry=false, + bool dry_run=false, + bool force=false, + bool record_only=false, + const StringArray&merge_options=StringArray() + ) throw (ClientException); + + virtual void + merge_peg(const Path&src, + const RevisionRange&range, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry, + bool dry_run, + bool force, + const StringArray&merge_options + ) throw (ClientException); + + /** + * Retrieve information for the given path + * remote or local. Only gives with subversion 1.2 + * usefull results + * + * @param path path for info + * @param rec recursive (if dir) + * @param rev for which revision + * @param peg_revision peg revision + * @return InfoEntries + * @since subversion 1.2 + */ + virtual InfoEntries + info(const Path &path, + Depth depth, + const Revision & rev, + const Revision & peg_revision=svn_opt_revision_unspecified, + const StringArray&changelists=StringArray() + ) throw (ClientException); + /** + * Retrieve log information for the given path + * Loads the log messages result set. The first + * entry is the youngest revision. + * + * You can use the constants Revision::START and + * Revision::HEAD + * + * @param path + * @param revisionStart Start revision. + * @param revisionEnd End revision + * @param revisionPeg Revision where path is valid. + * @param discoverChangedPaths Should changed pathes transferred + * @param strictNodeHistory + * @param limit the maximum log entries count. + * @param include_merged_revisions log information for revisions which have been merged to targets will also be returned. (subversion 1.5) + * @return a vector with log entries + */ + virtual LogEntriesPtr + log (const Path& path, const Revision & revisionStart, + const Revision & revisionEnd, + const Revision & revisionPeg, + bool discoverChangedPaths=false, + bool strictNodeHistory=true,int limit=0, + bool include_merged_revisions = false, + const StringArray&revprops=StringArray() + ) throw (ClientException); + /** + * Retrieve log information for the given path + * Loads the log messages result set. Result will stored + * in a map where the key is the revision number + * + * You can use the constants Revision::START and + * Revision::HEAD + * + * @param path + * @param revisionStart + * @param revisionEnd + * @param revisionPeg Revision where path is valid. + * @param target the logmap where to store the entries + * @param discoverChangedPaths + * @param strictNodeHistory + * @param limit (ignored when subversion 1.1 API) + * @return true if success + */ + virtual bool + log (const Path& path, const Revision & revisionStart, + const Revision & revisionEnd, + LogEntriesMap&target, + const Revision & revisionPeg, + bool discoverChangedPaths, + bool strictNodeHistory,int limit, + bool include_merged_revisions = false, + const StringArray&revprops=StringArray() + ) throw (ClientException); + + /** + * Produce diff output which describes the delta between + * @a path/@a revision1 and @a path/@a revision2. @a path + * can be either a working-copy path or a URL. + * + * A ClientException will be thrown if either @a revision1 or + * @a revision2 has an `unspecified' or unrecognized `kind'. + * + * @param tmpPath prefix for a temporary directory needed by diff. + * Filenames will have ".tmp" and similar added to this prefix in + * order to ensure uniqueness. + * @param path path of the file. + * @param revision1 one of the revisions to check. + * @param revision2 the other revision. + * @param recurse whether the operation should be done recursively. + * @param ignoreAncestry whether the files will be checked for + * relatedness. + * @param noDiffDeleted if true, no diff output will be generated on deleted files. + * @param ignore_contenttype if true generate diff even the items are marked as binaries + * @param extra extra options for diff ("-b", "-w","--ignore-eol-style") + * @return delta between the files + * @exception ClientException + */ + virtual QByteArray + diff_peg (const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype, + const StringArray&extra, + const StringArray&changelists + ) + throw (ClientException); + + /** + * Same as other diff but extra options and changelists always set to empty list. + */ + virtual QByteArray + diff_peg (const Path & tmpPath, const Path & path,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, const Revision& peg_revision, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype) + throw (ClientException); + + /** + * Produce diff output which describes the delta between + * @a path1/@a revision1 and @a path2/@a revision2. @a path2 + * can be either a working-copy path or a URL. + * + * A ClientException will be thrown if either @a revision1 or + * @a revision2 has an `unspecified' or unrecognized `kind'. + * + * @param tmpPath prefix for a temporary directory needed by diff. + * Filenames will have ".tmp" and similar added to this prefix in + * order to ensure uniqueness. + * @param path1 first file or folder to diff. + * @param path2 second file or folder to diff. + * @param revision1 one of the revisions to check (path1). + * @param revision2 the other revision (path2). + * @param recurse whether the operation should be done recursively. + * @param ignoreAncestry whether the files will be checked for + * relatedness. + * @param noDiffDeleted if true, no diff output will be generated on deleted files. + * @param ignore_contenttype if true generate diff even the items are marked as binaries + * @param extra extra options for diff ("-b", "-w","--ignore-eol-style") + * @return delta between the files + * @exception ClientException + */ + virtual QByteArray + diff (const Path & tmpPath, const Path & path1,const Path & path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype, + const StringArray&extra, + const StringArray&changelists + ) + throw (ClientException); + + /** + * Same as other diff but extra options always set to empty list. + */ + virtual QByteArray + diff (const Path & tmpPath, const Path & path1,const Path & path2,const Path&relativeTo, + const Revision & revision1, const Revision & revision2, + Depth depth, bool ignoreAncestry, + bool noDiffDeleted,bool ignore_contenttype) + throw (ClientException); + + /** + * lists entries in @a pathOrUrl no matter whether local or + * repository + * + * @param pathOrUrl + * @param revision + * @param peg at wich revision path exists + * @param depth @sa svn::Depth + * @param retrieve_locks check for REPOSITORY locks while listing + * @return a vector of directory entries, each with + * a relative path (only filename) + */ + virtual DirEntries + list (const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + svn::Depth depth,bool retrieve_locks) throw (ClientException); + + /** + * lists properties in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param peg most case should set to @a revision + * @param recurse + * @return PropertiesList + */ + virtual PathPropertiesMapListPtr + proplist(const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth=DepthEmpty, + const StringArray&changelists=StringArray()); + + /** + * lists one property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param peg most case should set to @a revision + * @param recurse + * @return PathPropertiesMapList + */ + virtual QPair<QLONG,PathPropertiesMapList> + propget(const QString& propName, + const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth = svn::DepthEmpty, + const StringArray&changelists=StringArray()); + + /** + * set property in @a path no matter whether local or + * repository + * + * @param path + * @param propName + * @param propValue + * @param recurse + * @param skip_check if true skip validity checks + * @return PropertiesList + */ + virtual void + propset(const QString& propName, + const QString& propValue, + const Path &path, + Depth depth=DepthEmpty, + bool skip_check=false, + const Revision&base_revision=Revision::UNDEFINED, + const StringArray&changelists=StringArray(), + const PropertiesMap&revProps=PropertiesMap() + ); + + /** + * delete property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param recurse + */ + virtual void + propdel(const QString& propName, + const Path &path, + Depth depth=DepthEmpty, + bool skip_check=false, + const Revision&base_revision=Revision::UNDEFINED, + const StringArray&changelists=StringArray()); + + + /** + * lists revision properties in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @return PropertiesList + */ + virtual QPair<QLONG,PropertiesMap> + revproplist(const Path &path, + const Revision &revision); + + /** + * lists one revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @return PropertiesList + */ + QPair<QLONG,QString> + revpropget(const QString& propName, + const Path &path, + const Revision &revision); + + /** + * set revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param propValue + * @param path + * @param revision + * @param force + * @return Revision + */ + virtual QLONG + revpropset(const QString& propName, + const QString& propValue, + const Path &path, + const Revision &revision, + bool force=false); + + /** + * delete revision property in @a path no matter whether local or + * repository + * + * @param propName + * @param path + * @param revision + * @param force + * @return Revision + */ + virtual QLONG + revpropdel(const QString& propName, + const Path &path, + const Revision &revision, + bool force=false); + + /** + * lock files in repository or working copy + * @param targets items to be locked + * @param message if non null stored with each lock in repository + * @param steal_lock if true locks in wc will stolen. + * @since subversion 1.2 + */ + virtual void + lock (const Targets & targets, + const QString& message, + bool steal_lock) throw (ClientException); + /** + * unlock files in repository or working copy + * @param targets items to unlock + * @param break_lock ignore any errors + */ + virtual void + unlock (const Targets&targets, + bool break_lock) throw (ClientException); + + virtual void + url2Revision(const QString&revstring, + Revision&start,Revision&end); + virtual void + url2Revision(const QString&revstring, + Revision&start); + + struct sBaton { + Context*m_context; + void*m_data; + void*m_revstack; + }; + + struct propBaton { + Context*m_context; + PathPropertiesMapList*resultlist; + }; + + private: + ContextP m_context; + + /** + * disallow assignment operator + */ + Client_impl & operator= (const Client &); + + /** + * disallow copy constructor + */ + Client_impl (const Client &); + + DirEntries + list_simple(const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + bool recurse) throw (ClientException); + DirEntries + list_locks(const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + bool recurse) throw (ClientException); + + svn_error_t * internal_cat(const Path & path, + const Revision & revision, + const Revision & peg_revision, + svn::stream::SvnStream&); + + apr_hash_t * map2hash(const PropertiesMap&,const Pool&); + }; + +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_lock.cpp b/src/svnqt/client_lock.cpp new file mode 100644 index 0000000..b70223d --- /dev/null +++ b/src/svnqt/client_lock.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +// svncpp +#include "client_impl.hpp" + +// subversion api +#include "svn_client.h" + +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/targets.hpp" +#include "svnqt/svnqt_defines.hpp" + +namespace svn +{ + + void + Client_impl::lock (const Targets & targets, + const QString& message, + bool steal_lock) throw (ClientException) + { + Pool pool; + svn_error_t * error = + svn_client_lock(const_cast<apr_array_header_t*> (targets.array (pool)), + message.TOUTF8(), + steal_lock, + *m_context, + pool); + if(error != NULL) + throw ClientException (error); + } + + void + Client_impl::unlock (const Targets&targets, + bool break_lock) throw (ClientException) + { + Pool pool; + svn_error_t * error = + svn_client_unlock(const_cast<apr_array_header_t*> (targets.array (pool)), + break_lock, + *m_context, + pool); + if(error != NULL) + throw ClientException (error); + } +} diff --git a/src/svnqt/client_ls.cpp b/src/svnqt/client_ls.cpp new file mode 100644 index 0000000..897a4d8 --- /dev/null +++ b/src/svnqt/client_ls.cpp @@ -0,0 +1,237 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif + + +// svncpp +#include "svnqt/client_impl.hpp" + +// subversion api +#include "svn_client.h" +#include "svn_path.h" +#include "svn_sorts.h" +//#include "svn_utf.h" + +#include "svnqt/dirent.hpp" +#include "svnqt/exception.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include "svnqt/helper.hpp" + +static int +compare_items_as_paths (const svn_sort__item_t *a, const svn_sort__item_t *b) +{ + return svn_path_compare_paths ((const char *)a->key, (const char *)b->key); +} + +namespace svn +{ + + DirEntries + Client_impl::list_simple(const Path& _p, + const Revision& revision, + const Revision& peg, + bool recurse) throw (ClientException) + { + Pool pool; + + apr_hash_t * hash; + /* don't want the lock hashs, so we simply use ls2 on svn 1.3, too. + * there is that method a cast to ls3 with lock_hash == 0 + */ + svn_error_t * error = + svn_client_ls2 (&hash, + _p.cstr(), + peg.revision(), + revision.revision(), + recurse, + *m_context, + pool); + + if (error != 0) + throw ClientException (error); + + apr_array_header_t * + array = svn_sort__hash ( + hash, compare_items_as_paths, pool); + + DirEntries entries; + + for (int i = 0; i < array->nelts; ++i) + { + const char *entryname; + svn_dirent_t *dirent; + svn_sort__item_t *item; + + item = &APR_ARRAY_IDX (array, i, svn_sort__item_t); + + entryname = static_cast<const char *>(item->key); + + dirent = static_cast<svn_dirent_t *> + (apr_hash_get (hash, entryname, item->klen)); + + entries.push_back (new DirEntry(QString::FROMUTF8(entryname), dirent)); + } + + return entries; + } + + DirEntries + Client_impl::list_locks(const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + bool recurse) throw (ClientException) + { + Pool pool; + + apr_hash_t * hash; + apr_hash_t * lock_hash; + + svn_error_t * error = + svn_client_ls3 (&hash, + &lock_hash, + pathOrUrl.cstr(), + peg, + revision, + recurse, + *m_context, + pool); + + if (error != 0) + throw ClientException (error); + + apr_array_header_t * + array = svn_sort__hash ( + hash, compare_items_as_paths, pool); + + DirEntries entries; + + for (int i = 0; i < array->nelts; ++i) + { + const char *entryname; + svn_dirent_t *dirent; + svn_lock_t * lockent; + svn_sort__item_t *item; + + item = &APR_ARRAY_IDX (array, i, svn_sort__item_t); + + entryname = static_cast<const char *>(item->key); + + dirent = static_cast<svn_dirent_t *> + (apr_hash_get (hash, entryname, item->klen)); + lockent = static_cast<svn_lock_t *> + (apr_hash_get(lock_hash,entryname,item->klen)); + entries.push_back (new DirEntry(QString::FROMUTF8(entryname), dirent,lockent)); + } + + return entries; + } + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + static svn_error_t * s_list_func + (void * baton,const char*path,const svn_dirent_t*dirent,const svn_lock_t*lock,const char* abs_path,apr_pool_t*) + { + Q_UNUSED(abs_path); + if (!baton || !path || !dirent) { + return 0; + } + /* check every loop for cancel of operation */ + Client_impl::sBaton * l_baton = (Client_impl::sBaton*)baton; + Context*l_context = l_baton->m_context; + DirEntries*entries = static_cast<DirEntries*>(l_baton->m_data); + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + entries->push_back(new DirEntry(QString::FROMUTF8(path),dirent,lock)); + return 0; + } +#endif + + DirEntries + Client_impl::list(const Path& pathOrUrl, + const Revision& revision, + const Revision& peg, + Depth depth,bool retrieve_locks) throw (ClientException) + { + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + sBaton _baton; + Pool pool; + DirEntries entries; + _baton.m_data = &entries; + _baton.m_context=m_context; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = svn_client_list2(pathOrUrl.cstr(), + peg, + revision, + svn::internal::DepthToSvn(depth), + SVN_DIRENT_ALL, + retrieve_locks, + s_list_func, + &_baton, + *m_context, + pool + ); +#else + bool recurse = depth==DepthInfinity; + svn_error_t * error = svn_client_list(pathOrUrl.cstr(), + peg, + revision, + recurse, + SVN_DIRENT_ALL, + retrieve_locks, + s_list_func, + &_baton, + *m_context, + pool + ); +#endif + if (error != 0) { + throw ClientException (error); + } + return entries; +#else + if (!retrieve_locks) { + return list_simple(pathOrUrl,revision,peg,depth==DepthInfinity); + } else { + return list_locks(pathOrUrl,revision,peg,depth==DepthInfinity); + } +#endif + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_merge.cpp b/src/svnqt/client_merge.cpp new file mode 100644 index 0000000..0d84cc2 --- /dev/null +++ b/src/svnqt/client_merge.cpp @@ -0,0 +1,180 @@ +#include "svnqt/client_impl.hpp" + +// subversion api +#include "svn_client.h" + +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/targets.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/stringarray.hpp" + +#include "svnqt/helper.hpp" + +namespace svn +{ +void Client_impl::merge (const Path & path1, const Revision & revision1, + const Path & path2, const Revision & revision2, + const Path & localPath, + bool force, + Depth depth, + bool notice_ancestry, + bool dry_run, + bool record_only, + const StringArray&merge_options + ) throw (ClientException) +{ + Pool pool; + svn_error_t * error = 0; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_merge3(path1.cstr (), + revision1.revision (), + path2.cstr (), + revision2.revision (), + localPath.cstr (), + internal::DepthToSvn(depth), + !notice_ancestry, + force, + record_only, + dry_run, + merge_options.array(pool), + *m_context, + pool); +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(record_only); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) + error = svn_client_merge2(path1.cstr (), + revision1.revision (), + path2.cstr (), + revision2.revision (), + localPath.cstr (), + recurse, + !notice_ancestry, + force, + dry_run, + merge_options.array(pool), + *m_context, + pool); +#else + Q_UNUSED(merge_options); + error = svn_client_merge(path1.cstr (), + revision1.revision (), + path2.cstr (), + revision2.revision (), + localPath.cstr (), + recurse, + !notice_ancestry, + force, + dry_run, + *m_context, + pool); +#endif +#endif + + if(error != 0) { + throw ClientException (error); + } + } + + void Client_impl::merge_peg(const Path&src, + const RevisionRanges&ranges, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry, + bool dry_run, + bool force, + bool record_only, + const StringArray&merge_options + ) throw (ClientException) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + Pool pool; + internal::RevisionRangesToHash _rhash(ranges); + + svn_error_t*error; + + error = svn_client_merge_peg3( + src.cstr(), + _rhash.array(pool), + peg, + targetWc.cstr(), + internal::DepthToSvn(depth), + !notice_ancestry, + force, + record_only, + dry_run, + merge_options.array(pool), + *m_context, + pool + ); + if(error != 0) { + throw ClientException (error); + } +#else + Q_UNUSED(record_only); + for (unsigned long i=0;i<ranges.count();++i) { + merge_peg(src,ranges[i],peg,targetWc,depth,notice_ancestry,dry_run,force,merge_options); + } +#endif + } + + void Client_impl::merge_peg(const Path&src, + const RevisionRange&range, + const Revision&peg, + const Path&targetWc, + Depth depth, + bool notice_ancestry, + bool dry_run, + bool force, + const StringArray&merge_options + ) throw (ClientException) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + RevisionRanges ranges; + ranges.append(range); + merge_peg(src,ranges,peg,targetWc,depth,notice_ancestry,dry_run,force,false,merge_options); +#else + Pool pool; + bool recurse=depth==DepthInfinity; + svn_error_t*error; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + error = svn_client_merge_peg2( + src.cstr(), + range.first, + range.second, + peg.revision(), + targetWc.cstr(), + recurse, + !notice_ancestry, + force, + dry_run, + merge_options.array(pool), + *m_context, + pool + ); +#else + Q_UNUSED(merge_options); + error = svn_client_merge_peg( + src.cstr(), + range.first, + range.second, + peg.revision(), + targetWc.cstr(), + recurse, + !notice_ancestry, + force, + dry_run, + *m_context, + pool + ); +#endif + if(error != 0) { + throw ClientException (error); + } +#endif + } + +} diff --git a/src/svnqt/client_modify.cpp b/src/svnqt/client_modify.cpp new file mode 100644 index 0000000..352760b --- /dev/null +++ b/src/svnqt/client_modify.cpp @@ -0,0 +1,722 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif +// svncpp +#include "svnqt/client_impl.hpp" + +// subversion api +#include "svn_client.h" + +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/targets.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/stringarray.hpp" + +#include "svnqt/helper.hpp" + +namespace svn +{ + svn_revnum_t + Client_impl::checkout (const Path& url, const Path & destPath, + const Revision & revision, + const Revision & peg, + svn::Depth depth, + bool ignore_externals, + bool overwrite + ) throw (ClientException) + { + Pool subPool; + svn_revnum_t revnum = 0; + Path up(url); + svn_error_t * error = 0; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_checkout3(&revnum, + up.cstr(), + destPath.cstr(), + peg.revision(), + revision.revision (), + internal::DepthToSvn(depth), + ignore_externals, + overwrite, + *m_context, + subPool); +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(overwrite); + error = svn_client_checkout2(&revnum, + up.cstr(), + destPath.cstr(), + peg.revision(), + revision.revision (), + recurse, + ignore_externals, + *m_context, + subPool); +#endif + if(error != NULL) + throw ClientException (error); + return revnum; + } + + Revision Client_impl::remove (const Path & path,bool force, + bool keep_local, + const PropertiesMap&revProps) throw (ClientException) + { + Targets targets (path.path()); + return remove(targets,force,keep_local,revProps); + } + + Revision + Client_impl::remove (const Targets & targets, + bool force, + bool keep_local, + const PropertiesMap&revProps + ) throw (ClientException) + { + Pool pool; + + svn_commit_info_t *commit_info = 0; + + svn_error_t * error = +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_client_delete3( + &commit_info, + targets.array(pool), + force, + keep_local, + map2hash(revProps,pool), + *m_context, + pool + ); +#else + svn_client_delete2 + (&commit_info, + const_cast<apr_array_header_t*> (targets.array (pool)), + force, + *m_context, + pool); + Q_UNUSED(keep_local); + Q_UNUSED(revProps); +#endif + if(error != 0) { + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; + } + + void + Client_impl::revert (const Targets & targets, + Depth depth, + const StringArray&changelist + ) throw (ClientException) + { + Pool pool; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = + svn_client_revert2 ((targets.array (pool)), + internal::DepthToSvn(depth), + changelist.array(pool), + *m_context, + pool); + +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(changelist); + svn_error_t * error = + svn_client_revert ((targets.array (pool)), + recurse, + *m_context, + pool); +#endif + if(error != NULL) { + throw ClientException (error); + } + } + + void + Client_impl::add (const Path & path, + svn::Depth depth,bool force, bool no_ignore, bool add_parents) throw (ClientException) + { + Pool pool; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = + svn_client_add4(path.cstr (), + internal::DepthToSvn(depth), + force, + no_ignore, + add_parents, + *m_context, + pool); +#else + Q_UNUSED(add_parents); + svn_error_t * error = + svn_client_add3 (path.cstr (), + depth==DepthInfinity, + force, + no_ignore, + *m_context, + pool); +#endif + if(error != NULL) + throw ClientException (error); + } + + Revisions + Client_impl::update (const Targets & path, + const Revision & revision, + Depth depth, + bool ignore_externals, + bool allow_unversioned, + bool sticky_depth + ) throw (ClientException) + { + Pool pool; + Revisions resulting; + svn_error_t * error; + + apr_pool_t *apr_pool = pool.pool(); + apr_array_header_t *apr_revisions = apr_array_make (apr_pool, + path.size(), + sizeof (svn_revnum_t)); + if (depth==DepthUnknown) { + depth=DepthInfinity; + } +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_update3(&apr_revisions,path.array(pool),revision,internal::DepthToSvn(depth),sticky_depth,ignore_externals,allow_unversioned,*m_context,pool); +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(sticky_depth); + Q_UNUSED(allow_unversioned); + error = svn_client_update2(&apr_revisions,path.array(pool),revision,recurse,ignore_externals,*m_context,pool); +#endif + if (error!=NULL) { + throw ClientException(error); + } + for (int i = 0; i < apr_revisions->nelts; ++i) + { + svn_revnum_t * _rev = + &APR_ARRAY_IDX (apr_revisions, i, svn_revnum_t); + + resulting.push_back((*_rev)); + } + return resulting; + } + + svn::Revision + Client_impl::commit (const Targets & targets, const QString& message, + svn::Depth depth,bool keep_locks, + const svn::StringArray&changelist, + const PropertiesMap&revProps, + bool keep_changelist) throw (ClientException) + { + Pool pool; + + m_context->setLogMessage (message); + svn_commit_info_t *commit_info = NULL; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = + svn_client_commit4 ( + &commit_info, + targets.array (pool), + internal::DepthToSvn(depth), + keep_locks, + keep_changelist, + changelist.array(pool), + map2hash(revProps,pool), + *m_context, + pool); +#else + Q_UNUSED(changelist); + Q_UNUSED(keep_changelist); + Q_UNUSED(revProps); + bool recurse = depth==DepthInfinity; + + svn_error_t * error = + svn_client_commit3 + (&commit_info, + targets.array (pool), + recurse, + keep_locks, + *m_context, + pool); +#endif + if (error != NULL) { + throw ClientException (error); + } + + if (commit_info && SVN_IS_VALID_REVNUM (commit_info->revision)) + return (commit_info->revision); + + return svn::Revision::UNDEFINED; + } + + Revision + Client_impl::copy(const Targets & srcPaths, + const Revision & srcRevision, + const Revision &pegRevision, + const Path & destPath, + bool asChild,bool makeParent, + const PropertiesMap&revProps + ) throw (ClientException) + { + if (srcPaths.size()<1) + { + throw ClientException("Wrong size of sources."); + } +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + Pool pool; + svn_commit_info_t *commit_info = 0L; + apr_array_header_t * sources = apr_array_make(pool,srcPaths.size(),sizeof(svn_client_copy_source_t *)); + for (size_t j=0;j<srcPaths.size();++j) + { + svn_client_copy_source_t* source = (svn_client_copy_source_t*)apr_palloc(pool, sizeof(svn_client_copy_source_t)); + source->path = apr_pstrdup(pool,srcPaths[j].path().TOUTF8()); + source->revision=srcRevision.revision(); + source->peg_revision=pegRevision.revision(); + APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source; + } + svn_error_t * error = + svn_client_copy4(&commit_info, + sources, + destPath.cstr(), + asChild,makeParent,map2hash(revProps,pool),*m_context,pool); + if (error!=0){ + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; +#else + Q_UNUSED(asChild); + Q_UNUSED(makeParent); + Q_UNUSED(revProps); + Q_UNUSED(pegRevision); + Revision rev; + if (srcPaths.size()>1 && !asChild) + { + throw ClientException("Multiple sources not allowed"); + } + + Path _dest; + QString base,dir; + for (size_t j=0;j<srcPaths.size();++j) + { + _dest=destPath; + if (asChild) { + srcPaths[j].split(dir,base); + _dest.addComponent(base); + } + rev = copy(srcPaths[j],srcRevision,_dest); + } + return rev; +#endif + } + + Revision + Client_impl::copy (const Path & srcPath, + const Revision & srcRevision, + const Path & destPath) throw (ClientException) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + return copy(srcPath,srcRevision,srcRevision,destPath,true,false); +#else + Pool pool; + svn_commit_info_t *commit_info = NULL; + svn_error_t * error = + svn_client_copy2 + (&commit_info, + srcPath.cstr (), + srcRevision.revision (), + destPath.cstr (), + *m_context, + pool); + + if(error != 0) { + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; +#endif + } + + svn::Revision Client_impl::move (const Path & srcPath, + const Path & destPath, + bool force) throw (ClientException) + { + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + return move(srcPath,destPath,force,false,false,PropertiesMap()); +#else + Pool pool; + svn_commit_info_t *commit_info = 0; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) + svn_error_t * error = svn_client_move4 +#else + svn_error_t * error = svn_client_move3 +#endif + (&commit_info, + srcPath.cstr (), + destPath.cstr (), + force, + *m_context, + pool); + + if(error != 0) { + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; +#endif + } + + svn::Revision Client_impl::move ( + const Targets & srcPaths, + const Path & destPath, + bool force, + bool asChild, + bool makeParent, + const PropertiesMap&revProps) throw (ClientException) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + Pool pool; + svn_commit_info_t *commit_info = 0; + svn_error_t * error = svn_client_move5( + &commit_info, + srcPaths.array(pool), + destPath.cstr(), + force, + asChild, + makeParent, + map2hash(revProps,pool), + *m_context, + pool + ); + if (error!=0) { + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; +#else + Q_UNUSED(makeParent); + Q_UNUSED(revProps); + Revision rev; + if (srcPaths.size()>1 && !asChild) + { + throw ClientException("Multiple sources not allowed"); + } + QString base,dir; + Path _dest; + for (size_t j=0;j<srcPaths.size();++j) + { + _dest=destPath; + if (asChild) { + srcPaths[j].split(dir,base); + _dest.addComponent(base); + } + rev = move(srcPaths[j],_dest,force); + } + return rev; +#endif + } + + svn::Revision + Client_impl::mkdir (const Path & path, + const QString& message, + bool makeParent, + const PropertiesMap&revProps + ) throw (ClientException) + { + Targets targets(path.path()); + return mkdir(targets,message,makeParent,revProps); + } + + svn::Revision + Client_impl::mkdir (const Targets & targets, + const QString&msg, + bool makeParent, + const PropertiesMap&revProps + ) throw (ClientException) + { + Pool pool; + m_context->setLogMessage(msg); + + svn_commit_info_t *commit_info = NULL; + + svn_error_t * error = 0; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_mkdir3 + (&commit_info, + const_cast<apr_array_header_t*>(targets.array (pool)), + makeParent, + map2hash(revProps,pool), + *m_context, pool); +#else + Q_UNUSED(makeParent); + Q_UNUSED(revProps); + error = svn_client_mkdir2 + (&commit_info, + const_cast<apr_array_header_t*>(targets.array (pool)), + *m_context, pool); +#endif + + /* important! otherwise next op on repository uses that logmessage again! */ + m_context->setLogMessage(QString::null); + + if(error != NULL) + throw ClientException (error); + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; + } + + void + Client_impl::cleanup (const Path & path) throw (ClientException) + { + Pool subPool; + apr_pool_t * apr_pool = subPool.pool (); + + svn_error_t * error = + svn_client_cleanup (path.cstr (), *m_context, apr_pool); + + if(error != NULL) + throw ClientException (error); + } + + void Client_impl::resolve(const Path & path,Depth depth,const ConflictResult&resolution) throw (ClientException) + { + Pool pool; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + const svn_wc_conflict_result_t*aResult=resolution.result(pool); + svn_error_t*error=svn_client_resolve(path.cstr(),internal::DepthToSvn(depth),aResult->choice,*m_context,pool); + +#else + Q_UNUSED(resolution); + bool recurse=depth==DepthInfinity; + svn_error_t * error = + svn_client_resolved (path.cstr (), + recurse, + *m_context, + pool); +#endif + if(error != NULL) { + throw ClientException (error); + } + } + + svn_revnum_t + Client_impl::doExport (const Path & srcPath, + const Path & destPath, + const Revision & revision, + const Revision & peg, + bool overwrite, + const QString&native_eol, + bool ignore_externals, + svn::Depth depth) throw (ClientException) + { + Pool pool; + svn_revnum_t revnum = 0; + const char*_neol; + if (native_eol==QString::null) { + _neol = (const char*)0; + } else { + _neol = native_eol.TOUTF8(); + } +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = + svn_client_export4(&revnum, + srcPath.cstr(), + destPath.cstr(), + peg.revision(), + revision.revision(), + overwrite, + ignore_externals, + internal::DepthToSvn(depth), + _neol, + *m_context, + pool); +#else + bool recurse = depth==svn::DepthInfinity; + svn_error_t * error = + svn_client_export3(&revnum, + srcPath.cstr(), + destPath.cstr(), + peg.revision(), + revision.revision(), + overwrite, + ignore_externals, + recurse, + _neol, + *m_context, + pool); +#endif + if(error != NULL) + throw ClientException (error); + return revnum; + } + + svn_revnum_t + Client_impl::doSwitch ( + const Path & path, const QString& url, + const Revision & revision, + Depth depth, + const Revision & peg, + bool sticky_depth, + bool ignore_externals, + bool allow_unversioned + ) throw (ClientException) + { + Pool pool; + svn_revnum_t revnum = 0; + svn_error_t * error = 0; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_switch2( + &revnum, + path.cstr(), + url.TOUTF8(), + peg.revision(), + revision.revision(), + internal::DepthToSvn(depth), + sticky_depth, + ignore_externals, + allow_unversioned, + *m_context, + pool + ); +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(peg); + Q_UNUSED(sticky_depth); + Q_UNUSED(ignore_externals); + Q_UNUSED(allow_unversioned); + error = svn_client_switch (&revnum, + path.cstr(), + url.TOUTF8(), + revision.revision (), + recurse, + *m_context, + pool); +#endif + if(error != NULL) { + throw ClientException (error); + } + return revnum; + } + + Revision + Client_impl::import (const Path & path, + const QString& url, + const QString& message, + svn::Depth depth, + bool no_ignore,bool no_unknown_nodetype, + const PropertiesMap&revProps + ) throw (ClientException) + + { + svn_commit_info_t *commit_info = NULL; + Pool pool; + + m_context->setLogMessage (message); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = + svn_client_import3(&commit_info,path.cstr (),url.TOUTF8(), + internal::DepthToSvn(depth),no_ignore,no_unknown_nodetype, + map2hash(revProps,pool), + *m_context,pool); +#else + bool recurse = depth==DepthInfinity; + Q_UNUSED(revProps); + Q_UNUSED(no_unknown_nodetype); + + svn_error_t * error = + svn_client_import2(&commit_info, + path.cstr (), + url.TOUTF8(), + !recurse, + no_ignore, + *m_context, + pool); +#endif + /* important! otherwise next op on repository uses that logmessage again! */ + m_context->setLogMessage(QString::null); + + if(error != 0) { + throw ClientException (error); + } + if (commit_info) { + return commit_info->revision; + } + return Revision::UNDEFINED; + } + + void + Client_impl::relocate (const Path & path, + const QString& from_url, + const QString& to_url, + bool recurse) throw (ClientException) + { + Pool pool; + svn_error_t * error = + svn_client_relocate (path.cstr (), + from_url.TOUTF8(), + to_url.TOUTF8(), + recurse, + *m_context, + pool); + + if(error != NULL) + throw ClientException (error); + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_property.cpp b/src/svnqt/client_property.cpp new file mode 100644 index 0000000..6438ff6 --- /dev/null +++ b/src/svnqt/client_property.cpp @@ -0,0 +1,450 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif +// svncpp +#include "svnqt/client_impl.hpp" + +// subversion api +#include "svn_client.h" +//#include "svn_utf.h" + +#include "svnqt/path.hpp" +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include "svnqt/helper.hpp" + + +namespace svn +{ + + static svn_error_t* ProplistReceiver(void*baton,const char*path,apr_hash_t*prop_hash,apr_pool_t*pool) + { + Client_impl::propBaton*_baton=(Client_impl::propBaton*)baton; + PropertiesMap prop_map; + PathPropertiesMapList*mapList = (PathPropertiesMapList*)_baton->resultlist; + + Context*l_context = _baton->m_context; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + + apr_hash_index_t *hi; + for (hi = apr_hash_first (pool, prop_hash); hi; + hi = apr_hash_next (hi)) + { + const void *key; + void *val; + + apr_hash_this (hi, &key, NULL, &val); + prop_map[ QString::FROMUTF8( (const char *)key ) ] = + QString::FROMUTF8( ((const svn_string_t *)val)->data ); + } + mapList->push_back(PathPropertiesMapEntry(QString::FROMUTF8(path), prop_map )); + return 0; + } + + PathPropertiesMapListPtr + Client_impl::proplist(const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth, + const StringArray&changelists) + { + Pool pool; + + PathPropertiesMapListPtr path_prop_map_list = PathPropertiesMapListPtr(new PathPropertiesMapList); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + propBaton baton; + baton.m_context=m_context; + baton.resultlist=path_prop_map_list; + svn_error_t * error = + svn_client_proplist3( + path.cstr (), + peg.revision(), + revision.revision (), + internal::DepthToSvn(depth), + changelists.array(pool), + ProplistReceiver, + &baton, + *m_context, + pool); +#else + Q_UNUSED(changelists); + Q_UNUSED(ProplistReceiver); + bool recurse=depth==DepthInfinity; + apr_array_header_t * props; + svn_error_t * error = + svn_client_proplist2(&props, + path.cstr (), + peg.revision(), + revision.revision (), + recurse, + *m_context, + pool); + +#endif + if(error != NULL) + { + throw ClientException (error); + } + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR < 5)) + for (int j = 0; j < props->nelts; ++j) + { + svn_client_proplist_item_t *item = + ((svn_client_proplist_item_t **)props->elts)[j]; + + PropertiesMap prop_map; + + apr_hash_index_t *hi; + for (hi = apr_hash_first (pool, item->prop_hash); hi; + hi = apr_hash_next (hi)) + { + const void *key; + void *val; + + apr_hash_this (hi, &key, NULL, &val); + prop_map[ QString::FROMUTF8( (const char *)key ) ] = + QString::FROMUTF8( ((const svn_string_t *)val)->data ); + } + + path_prop_map_list->push_back( PathPropertiesMapEntry( QString::FROMUTF8(item->node_name->data), prop_map ) ); + } +#endif + return path_prop_map_list; + } + + QPair<QLONG,PathPropertiesMapList> + Client_impl::propget(const QString& propName, + const Path &path, + const Revision &revision, + const Revision &peg, + Depth depth, + const StringArray&changelists + ) + { + Pool pool; + + apr_hash_t *props; + svn_revnum_t actual = svn_revnum_t(-1); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_error_t * error = svn_client_propget3(&props, + propName.TOUTF8(), + path.cstr (), + peg.revision(), + revision.revision (), + &actual, + internal::DepthToSvn(depth), + changelists.array(pool), + *m_context, + pool + ); +#else + bool recurse=depth==DepthInfinity; + Q_UNUSED(changelists); + svn_error_t * error = + svn_client_propget2(&props, + propName.TOUTF8(), + path.cstr (), + peg.revision(), + revision.revision (), + recurse, + *m_context, + pool); +#endif + + if(error != NULL) + { + throw ClientException (error); + } + + PathPropertiesMapList path_prop_map_list; + + + apr_hash_index_t *hi; + for (hi = apr_hash_first (pool, props); hi; + hi = apr_hash_next (hi)) + { + PropertiesMap prop_map; + + const void *key; + void *val; + + apr_hash_this (hi, &key, NULL, &val); + prop_map[propName] = QString::FROMUTF8( ((const svn_string_t *)val)->data ); + path_prop_map_list.push_back( PathPropertiesMapEntry(QString::FROMUTF8((const char *)key), prop_map ) ); + } + + return QPair<QLONG,PathPropertiesMapList>(actual,path_prop_map_list); + } + + void + Client_impl::propset(const QString& propName, + const QString& propValue, + const Path &path, + Depth depth, + bool skip_checks, + const Revision&base_revision, + const StringArray&changelists, + const PropertiesMap&revProps + ) + { + Pool pool; + const svn_string_t * propval; + + if (propValue.isNull()) { + propval=0; + } else { + propval = svn_string_create (propValue.TOUTF8(),pool); + } + + svn_error_t * error = 0; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_commit_info_t * commit_info; + svn_client_propset3( + &commit_info, + propName.TOUTF8(), + propval, path.cstr(), + internal::DepthToSvn(depth),skip_checks, + base_revision, + changelists.array(pool), + map2hash(revProps,pool), + *m_context, pool); + +#else + Q_UNUSED(changelists); + Q_UNUSED(base_revision); + Q_UNUSED(revProps); + bool recurse = depth==DepthInfinity; + svn_client_propset2( + propName.TOUTF8(), + propval, path.cstr(), + recurse,skip_checks, *m_context, pool); +#endif + if(error != NULL) { + throw ClientException (error); + } + } + + void + Client_impl::propdel(const QString& propName, + const Path &path, + Depth depth, + bool skip_checks, + const Revision&base_revision, + const StringArray&changelists) + { + propset(propName,QString::null,path,depth,skip_checks,base_revision,changelists); + } + +//-------------------------------------------------------------------------------- +// +// revprop functions +// +//-------------------------------------------------------------------------------- + /** + * lists revision properties in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param recurse + * @return PropertiesList + */ + QPair<QLONG,PropertiesMap> + Client_impl::revproplist(const Path &path, + const Revision &revision) + { + Pool pool; + + apr_hash_t * props; + svn_revnum_t revnum; + svn_error_t * error = + svn_client_revprop_list (&props, + path.cstr (), + revision.revision (), + &revnum, + *m_context, + pool); + if(error != NULL) + { + throw ClientException (error); + } + + PropertiesMap prop_map; + + apr_hash_index_t *hi; + for (hi = apr_hash_first (pool, props); hi; + hi = apr_hash_next (hi)) + { + const void *key; + void *val; + + apr_hash_this (hi, &key, NULL, &val); + prop_map[ QString::FROMUTF8( (const char *)key ) ] = QString::FROMUTF8( ((const svn_string_t *)val)->data ); + } + + return QPair<QLONG,PropertiesMap>( revnum, prop_map ); + } + + /** + * lists one revision property in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param recurse + * @return PropertiesList + */ + + QPair<QLONG,QString> + Client_impl::revpropget(const QString& propName, + const Path &path, + const Revision &revision) + { + Pool pool; + + svn_string_t *propval; + svn_revnum_t revnum; + svn_error_t * error = + svn_client_revprop_get ( + propName.TOUTF8(), + &propval, + path.cstr (), + revision.revision (), + &revnum, + *m_context, + pool); + if(error != NULL) + { + throw ClientException (error); + } + + // if the property does not exist NULL is returned + if( propval == NULL ) + return QPair<QLONG,QString>( 0, QString() ); + + return QPair<QLONG,QString>( revnum, QString::FROMUTF8(propval->data) ); + } + + /** + * set property in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param propName + * @param propValue + * @param recurse + * @param revprop + * @return PropertiesList + */ + QLONG + Client_impl::revpropset(const QString& propName, + const QString& propValue, + const Path &path, + const Revision &revision, + bool force) + { + Pool pool; + + const svn_string_t * propval + = svn_string_create ( + propValue.TOUTF8(), + pool); + + svn_revnum_t revnum; + svn_error_t * error = + svn_client_revprop_set ( + propName.TOUTF8(), + propval, + path.cstr (), + revision.revision (), + &revnum, + force, + *m_context, + pool); + if(error != NULL) + throw ClientException (error); + + return revnum; + } + + /** + * delete property in @a path no matter whether local or + * repository + * + * @param path + * @param revision + * @param propName + * @param propValue + * @param recurse + * @param revprop + * @return PropertiesList + */ + QLONG + Client_impl::revpropdel(const QString& propName, + const Path &path, + const Revision &revision, + bool force) + { + Pool pool; + + svn_revnum_t revnum; + svn_error_t * error = + svn_client_revprop_set ( + propName.TOUTF8(), + 0, // value = NULL + path.cstr (), + revision.revision (), + &revnum, + force, + *m_context, + pool); + if(error != NULL) + throw ClientException (error); + + return revnum; + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/client_status.cpp b/src/svnqt/client_status.cpp new file mode 100644 index 0000000..17f51e6 --- /dev/null +++ b/src/svnqt/client_status.cpp @@ -0,0 +1,736 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2008 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif + + +// svncpp +#include "svnqt/client_impl.hpp" +#include "svnqt/helper.hpp" + +// Subversion api +#include "svn_client.h" +#include "svn_sorts.h" +#include "svn_path.h" +//#include "svn_utf.h" + +#include "svnqt/dirent.hpp" +#include "svnqt/exception.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/status.hpp" +#include "svnqt/targets.hpp" +#include "svnqt/info_entry.hpp" +#include "svnqt/url.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/context_listener.hpp" + +namespace svn +{ + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + static svn_error_t * + logReceiver2( + void*baton, + svn_log_entry_t *log_entry, + apr_pool_t * pool + ) + { + Client_impl::sBaton * l_baton = (Client_impl::sBaton*)baton; + LogEntries * entries = + (LogEntries *) l_baton->m_data; + QLIST<QLONG>*rstack= + (QLIST<QLONG>*)l_baton->m_revstack; + Context*l_context = l_baton->m_context; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + if (! SVN_IS_VALID_REVNUM(log_entry->revision)) + { + if (rstack&&rstack->size()>0) { + rstack->pop_front(); + } + return SVN_NO_ERROR; + } + entries->insert (entries->begin (), LogEntry (log_entry)); + if (rstack) { + entries->first().m_MergedInRevisions=(*rstack); + if (log_entry->has_children) { + rstack->push_front(log_entry->revision); + } + } + return SVN_NO_ERROR; + } +#else + static svn_error_t * + logReceiver ( + void *baton, + apr_hash_t * changedPaths, + svn_revnum_t rev, + const char *author, + const char *date, + const char *msg, + apr_pool_t * pool + ) + { + Client_impl::sBaton * l_baton = (Client_impl::sBaton*)baton; + LogEntries * entries = + (LogEntries *) l_baton->m_data; + + /* check every loop for cancel of operation */ + Context*l_context = l_baton->m_context; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + entries->insert (entries->begin (), LogEntry (rev, author, date, msg)); + if (changedPaths != NULL) + { + LogEntry &entry = entries->front (); + + for (apr_hash_index_t *hi = apr_hash_first (pool, changedPaths); + hi != NULL; + hi = apr_hash_next (hi)) + { + const void *pv; + void *val; + apr_hash_this (hi, &pv, NULL, &val); + + svn_log_changed_path_t *log_item = reinterpret_cast<svn_log_changed_path_t *> (val); + const char* path = reinterpret_cast<const char*>(pv); + + entry.changedPaths.push_back ( + LogChangePathEntry (path, + log_item->action, + log_item->copyfrom_path, + log_item->copyfrom_rev) ); + + } + } + + return SVN_NO_ERROR; + } +#endif + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + static svn_error_t * + logMapReceiver2( + void*baton, + svn_log_entry_t *log_entry, + apr_pool_t * pool + ) + { + Client_impl::sBaton * l_baton = (Client_impl::sBaton*)baton; + LogEntriesMap * entries = + (LogEntriesMap *) l_baton->m_data; + Context*l_context = l_baton->m_context; + QLIST<QLONG>*rstack= + (QLIST<QLONG>*)l_baton->m_revstack; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + if (! SVN_IS_VALID_REVNUM(log_entry->revision)) + { + if (rstack&&rstack->size()>0) { + rstack->pop_front(); + } + return SVN_NO_ERROR; + } + (*entries)[log_entry->revision]=LogEntry (log_entry); + /// @TODO insert it into last logentry + if (rstack) { + (*entries)[log_entry->revision].m_MergedInRevisions=(*rstack); + if (log_entry->has_children) { + rstack->push_front(log_entry->revision); + } + } + return SVN_NO_ERROR; + } +#else + static svn_error_t * + logMapReceiver (void *baton, + apr_hash_t * changedPaths, + svn_revnum_t rev, + const char *author, + const char *date, + const char *msg, + apr_pool_t * pool + ) + { + Client_impl::sBaton * l_baton = (Client_impl::sBaton*)baton; + LogEntriesMap * entries = + (LogEntriesMap *) l_baton->m_data; + + /* check every loop for cancel of operation */ + Context*l_context = l_baton->m_context; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + (*entries)[rev]=LogEntry(rev, author, date, msg); + if (changedPaths != NULL) + { + LogEntry &entry = (*entries)[rev]; + + for (apr_hash_index_t *hi = apr_hash_first (pool, changedPaths); + hi != NULL; + hi = apr_hash_next (hi)) + { + const void *pv; + void *val; + apr_hash_this (hi, &pv, NULL, &val); + + svn_log_changed_path_t *log_item = reinterpret_cast<svn_log_changed_path_t *> (val); + const char* path = reinterpret_cast<const char*>(pv); + + entry.changedPaths.push_back ( + LogChangePathEntry (path, + log_item->action, + log_item->copyfrom_path, + log_item->copyfrom_rev) ); + + } + } + + return NULL; + } +#endif + + struct StatusEntriesBaton { + apr_pool_t* pool; + apr_hash_t* hash; + Context*m_Context; + StatusEntriesBaton() { + pool = 0; + hash = 0; + m_Context = 0; + } + }; + + static svn_error_t * InfoEntryFunc(void*baton, + const char*path, + const svn_info_t*info, + apr_pool_t *) + { + StatusEntriesBaton* seb = (StatusEntriesBaton*)baton; + if (seb->m_Context) { + /* check every loop for cancel of operation */ + Context*l_context = seb->m_Context; + svn_client_ctx_t*ctx = l_context->ctx(); + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + } + path = apr_pstrdup (seb->pool, path); + InfoEntry*e = new InfoEntry(info,path); + apr_hash_set (seb->hash, path, APR_HASH_KEY_STRING, e); + return NULL; + } + + static void StatusEntriesFunc (void *baton, + const char *path, + svn_wc_status2_t *status) + { + svn_wc_status2_t* stat; + StatusEntriesBaton* seb = (StatusEntriesBaton*)baton; + + path = apr_pstrdup (seb->pool, path); + stat = svn_wc_dup_status2 (status, seb->pool); + apr_hash_set (seb->hash, path, APR_HASH_KEY_STRING, stat); + } + + static StatusEntries + localStatus (const Path& path, + Depth depth, + const bool get_all, + const bool update, + const bool no_ignore, + const bool hide_externals, + const StringArray & changelists, + Context * context) + { + svn_error_t *error; + StatusEntries entries; + apr_hash_t *status_hash; + svn_revnum_t revnum; + Revision rev (Revision::HEAD); + Pool pool; + StatusEntriesBaton baton; + + status_hash = apr_hash_make (pool); + baton.hash = status_hash; + baton.pool = pool; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_status3 ( + &revnum, // revnum + path.path().TOUTF8(), // path + rev, + StatusEntriesFunc, // status func + &baton, // status baton + internal::DepthToSvn(depth), // see svn::Depth + get_all, // get all not only interesting + update, // check for updates + no_ignore, // hide ignored files or not + hide_externals, // hide external + changelists.array(pool), + *context, //client ctx + pool); +#else + Q_UNUSED(changelists); + error = svn_client_status2 ( + &revnum, // revnum + path.path().TOUTF8(), // path + rev, + StatusEntriesFunc, // status func + &baton, // status baton + (depth==DepthInfinity), //recurse + get_all, // get all not only interesting + update, // check for updates + no_ignore, // hide ignored files or not + hide_externals, // hide external + *context, //client ctx + pool); +#endif + + if (error!=NULL) + { + throw ClientException (error); + } + + apr_array_header_t *statusarray = + svn_sort__hash (status_hash, svn_sort_compare_items_as_paths, + pool); + int i; + + /* Loop over array, printing each name/status-structure */ + for (i = 0; i < statusarray->nelts; ++i) + { + const svn_sort__item_t *item; + const char *filePath; + svn_wc_status2_t *status = NULL; + + item = &APR_ARRAY_IDX (statusarray, i, const svn_sort__item_t); + status = (svn_wc_status2_t *) item->value; + + filePath = (const char *) item->key; + entries.push_back (StatusPtr(new Status(filePath, status))); + } + return entries; + } + + static StatusPtr + dirEntryToStatus (const Path& path, DirEntryPtr dirEntry) + { + QString url = path.path(); + url += QString::FROMUTF8("/"); + url += dirEntry->name(); + return StatusPtr(new Status (url, dirEntry)); + } + + static StatusPtr + infoEntryToStatus(const Path&,const InfoEntry&infoEntry) + { + return StatusPtr(new Status(infoEntry.url(),infoEntry)); + } + + static StatusEntries + remoteStatus (Client * client, + const Path& path, + Depth depth, + const bool , + const bool , + const bool , + const Revision revision, + Context * , + bool detailed_remote) + { + DirEntries dirEntries = client->list(path, revision, revision, depth,detailed_remote); + DirEntries::const_iterator it; + + StatusEntries entries; + QString url = path.path(); + url+=QString::FROMUTF8("/"); + + for (it = dirEntries.begin (); it != dirEntries.end (); it++) + { + DirEntryPtr dirEntry = *it; + if (dirEntry->name().isEmpty()) + continue; + entries.push_back(dirEntryToStatus (path, dirEntry)); + } + return entries; + } + + StatusEntries + Client_impl::status (const Path& path, + Depth depth, + const bool get_all, + const bool update, + const bool no_ignore, + const Revision revision, + bool detailed_remote, + const bool hide_externals, + const StringArray & changelists) throw (ClientException) + { + if (Url::isValid (path.path())) { + return remoteStatus (this, path, depth, get_all, update, + no_ignore,revision,m_context,detailed_remote); + } else { + return localStatus (path, depth, get_all, update, + no_ignore, hide_externals,changelists, m_context); + } + } + + static StatusPtr + localSingleStatus (const Path& path, Context * context,bool update=false) + { + svn_error_t *error; + apr_hash_t *status_hash; + Pool pool; + StatusEntriesBaton baton; + svn_revnum_t revnum; + Revision rev (Revision::HEAD); + + status_hash = apr_hash_make( pool ); + baton.hash = status_hash; + baton.pool = pool; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_status3 ( + &revnum, // revnum + path.path().TOUTF8(), // path + rev, + StatusEntriesFunc, // status func + &baton, // status baton + svn_depth_empty, // not recurse + true, // get all not only interesting + update, // check for updates + false, // hide ignored files or not + false, // hide external + 0, + *context, //client ctx + pool); +#else + error = svn_client_status2 ( + &revnum, // revnum + path.path().TOUTF8(), // path + rev, + StatusEntriesFunc, // status func + &baton, // status baton + false, + true, + update, + false, + false, + *context, //client ctx + pool); +#endif + if (error != NULL) + { + throw ClientException (error); + } + + apr_array_header_t *statusarray = + svn_sort__hash (status_hash, svn_sort_compare_items_as_paths, + pool); + const svn_sort__item_t *item; + const char *filePath; + svn_wc_status2_t *status = NULL; + + item = &APR_ARRAY_IDX (statusarray, 0, const svn_sort__item_t); + status = (svn_wc_status2_t *) item->value; + filePath = (const char *) item->key; + + return StatusPtr(new Status (filePath, status)); + }; + + static StatusPtr + remoteSingleStatus (Client * client, const Path& path,const Revision revision, Context * ) + { + InfoEntries infoEntries = client->info(path,DepthEmpty,revision,Revision(Revision::UNDEFINED)); + if (infoEntries.size () == 0) + return StatusPtr(new Status()); + else + return infoEntryToStatus (path, infoEntries [0]); + } + + StatusPtr + Client_impl::singleStatus (const Path& path,bool update,const Revision revision) throw (ClientException) + { + if (Url::isValid (path.path())) + return remoteSingleStatus (this, path,revision, m_context); + else + return localSingleStatus (path, m_context,update); + } + + bool + Client_impl::log (const Path& path, const Revision & revisionStart, + const Revision & revisionEnd, + LogEntriesMap&log_target, + const Revision & revisionPeg, + bool discoverChangedPaths, + bool strictNodeHistory,int limit, + bool include_merged_revisions, + const StringArray&revprops + ) throw (ClientException) + { + Targets target(path); + Pool pool; + sBaton l_baton; + QLIST<QLONG> revstack; + l_baton.m_context=m_context; + l_baton.m_data = &log_target; + l_baton.m_revstack = &revstack; + svn_error_t *error; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_log4 ( + target.array (pool), + revisionPeg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + include_merged_revisions?1:0, + revprops.array(pool), + logMapReceiver2, + &l_baton, + *m_context, // client ctx + pool); +#elif ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + Q_UNUSED(include_merged_revisions); + Q_UNUSED(revprops); + + error = svn_client_log3 ( + target.array (pool), + revisionPeg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + logMapReceiver, + &l_baton, + *m_context, // client ctx + pool); +#else + Q_UNUSED(include_merged_revisions); + Q_UNUSED(revprops); + Q_UNUSED(revisionPeg); + + error = svn_client_log2 ( + target.array (pool), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + logMapReceiver, + &l_baton, + *m_context, // client ctx + pool); +#endif + if (error != NULL) + { + throw ClientException (error); + } + return true; + } + + LogEntriesPtr + Client_impl::log (const Path& path, const Revision & revisionStart, + const Revision & revisionEnd, const Revision & revisionPeg, + bool discoverChangedPaths, + bool strictNodeHistory,int limit, + bool include_merged_revisions, + const StringArray&revprops + ) throw (ClientException) + { + Targets target(path); + Pool pool; + LogEntriesPtr entries = LogEntriesPtr(new LogEntries ()); + QLIST<QLONG> revstack; + sBaton l_baton; + l_baton.m_context=m_context; + l_baton.m_data = entries; + l_baton.m_revstack = &revstack; + + svn_error_t *error; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = svn_client_log4 ( + target.array (pool), + revisionPeg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + include_merged_revisions?1:0, + revprops.array(pool), + logReceiver2, + &l_baton, + *m_context, // client ctx + pool); +#elif ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + Q_UNUSED(include_merged_revisions); + Q_UNUSED(revprops); + + error = svn_client_log3 ( + target.array (pool), + revisionPeg.revision(), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + logReceiver, + &l_baton, + *m_context, // client ctx + pool); +#else + Q_UNUSED(include_merged_revisions); + Q_UNUSED(revprops); + Q_UNUSED(revisionPeg); + + error = svn_client_log2 ( + target.array (pool), + revisionStart.revision (), + revisionEnd.revision (), + limit, + discoverChangedPaths ? 1 : 0, + strictNodeHistory ? 1 : 0, + logReceiver, + &l_baton, + *m_context, // client ctx + pool); +#endif + if (error != NULL) + { + throw ClientException (error); + } + + return entries; + } + + InfoEntries + Client_impl::info(const Path& _p, + Depth depth, + const Revision & rev, + const Revision & peg_revision, + const StringArray&changelists + ) throw (ClientException) + { + + InfoEntries ientries; + Pool pool; + svn_error_t *error = NULL; + StatusEntriesBaton baton; + apr_hash_t *status_hash; + + status_hash = apr_hash_make (pool); + baton.hash = status_hash; + baton.pool = pool; + baton.m_Context=m_context; + svn_opt_revision_t pegr; + const char *truepath = 0; + bool internal_peg = false; + QByteArray _buf = _p.cstr(); + + error = svn_opt_parse_path(&pegr, &truepath, + _buf, + pool); + if (error != NULL) + throw ClientException (error); + + if (peg_revision.kind() == svn_opt_revision_unspecified) { + if ((svn_path_is_url (_p.cstr())) && (pegr.kind == svn_opt_revision_unspecified)) { + pegr.kind = svn_opt_revision_head; + internal_peg=true; + } + } + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + error = + svn_client_info2(truepath, + internal_peg?&pegr:peg_revision.revision(), + rev.revision (), + &InfoEntryFunc, + &baton, + internal::DepthToSvn(depth), + changelists.array(pool), + *m_context, //client ctx + pool); +#else + bool rec = depth==DepthInfinity; + Q_UNUSED(changelists); + error = + svn_client_info(truepath, + internal_peg?&pegr:peg_revision.revision(), + rev.revision (), + &InfoEntryFunc, + &baton, + rec, + *m_context, //client ctx + pool); +#endif + + if (error != NULL) + throw ClientException (error); + + apr_array_header_t *statusarray = + svn_sort__hash (status_hash, svn_sort_compare_items_as_paths, + pool); + int i; + + /* Loop over array, printing each name/status-structure */ + for (i=0; i< statusarray->nelts; ++i) + { + const svn_sort__item_t *item; + InfoEntry*e = NULL; + item = &APR_ARRAY_IDX (statusarray, i, const svn_sort__item_t); + e = (InfoEntry *) item->value; + ientries.push_back(*e); + delete e; + } + if (error != NULL) + throw ClientException (error); + return ientries; + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/cmakemodules/FindSqlite.cmake b/src/svnqt/cmakemodules/FindSqlite.cmake new file mode 100644 index 0000000..3c50d33 --- /dev/null +++ b/src/svnqt/cmakemodules/FindSqlite.cmake @@ -0,0 +1,32 @@ +IF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + SET(SQLITE_FOUND TRUE) +ELSE (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + INCLUDE(UsePkgConfig) + PKGCONFIG(sqlite3 _sqliteincdir _sqlitelibdir _sqlitelinkflags _sqlitecflags) + + FIND_PATH(SQLITE_INCLUDE_DIR sqlite3.h + ${_sqliteincdir} + /usr/include + /usr/local/include + ) + FIND_LIBRARY(SQLITE_LIBRARIES NAMES sqlite3 + PATHS + ${_sqlitelibdir} + /usr/lib + /usr/local/lib + ) + + IF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + SET(SQLITE_FOUND TRUE) + ENDIF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) + + IF (SQLITE_FOUND) + MESSAGE(STATUS "Found sqlite3: ${SQLITE_LIBRARIES}") + ELSE (SQLITE_FOUND) + MESSAGE(STATUS "Could not find sqlite3") + ADD_DEFINITIONS(-DNO_SQLITE3) + ENDIF (SQLITE_FOUND) + + MARK_AS_ADVANCED(SQLITE_LIBRARIES SQLITE_INCLUDE_DIR) + +ENDIF (SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES) diff --git a/src/svnqt/cmakemodules/FindSubversion.cmake b/src/svnqt/cmakemodules/FindSubversion.cmake new file mode 100644 index 0000000..358ee3a --- /dev/null +++ b/src/svnqt/cmakemodules/FindSubversion.cmake @@ -0,0 +1,352 @@ +SET(SUBVERSIONFOUND) +SET(SUBVERSION_ALL_LIBS) + +INCLUDE (CheckIncludeFiles) + +#search libraries for UNIX +IF (UNIX) + + MACRO(FIND_SUB_LIB targetvar libname) + IF (SUBVERSION_INSTALL_PATH) + FIND_LIBRARY(${targetvar} ${libname} + PATHS + ${SUBVERSION_INSTALL_PATH}/lib + NO_DEFAULT_PATH + ) + ENDIF(SUBVERSION_INSTALL_PATH) + FIND_LIBRARY(${targetvar} ${libname} + PATHS + /usr/lib + /usr/local/lib + ) + ENDMACRO(FIND_SUB_LIB) + + IF (SUBVERSION_INSTALL_PATH) + FIND_PATH(SUBVERSION_INCLUDE_DIR svn_client.h + PATHS + ${SUBVERSION_INSTALL_PATH}/include/subversion-1 + NO_DEFAULT_PATH + ) + ENDIF (SUBVERSION_INSTALL_PATH) + FIND_PATH(SUBVERSION_INCLUDE_DIR svn_client.h + /usr/include/subversion-1 + /usr/local/include/subversion-1) + + FIND_SUB_LIB(SUBVERSION_CLIENTLIB svn_client-1) + FIND_SUB_LIB(SUBVERSION_REPOSITORYLIB svn_repos-1) + FIND_SUB_LIB(SUBVERSION_WCLIB svn_wc-1) + FIND_SUB_LIB(SUBVERSION_FSLIB svn_fs-1) + FIND_SUB_LIB(SUBVERSION_SUBRLIB svn_subr-1) + FIND_SUB_LIB(SUBVERSION_RALIB svn_ra-1) + FIND_SUB_LIB(SUBVERSION_DIFFLIB svn_diff-1) + + FIND_PROGRAM(APR_CONFIG NAMES apr-config apr-1-config + PATHS + /usr/local/apr/bin + ) + + FIND_PROGRAM(APU_CONFIG NAMES apu-config apu-1-config + PATHS + /usr/local/apr/bin + ) + + if(NOT APR_CONFIG) + MESSAGE(SEND_ERROR "Error: no apr-config found") + endif(NOT APR_CONFIG) + + if(NOT APU_CONFIG) + MESSAGE(SEND_ERROR "Error: no apu-config found") + endif(NOT APU_CONFIG) + + EXEC_PROGRAM(${APR_CONFIG} ARGS "--includedir" OUTPUT_VARIABLE APR_INCLUDE_DIR) + EXEC_PROGRAM(${APU_CONFIG} ARGS "--includedir" OUTPUT_VARIABLE APU_INCLUDE_DIR) + + EXEC_PROGRAM(${APR_CONFIG} ARGS "--cppflags" OUTPUT_VARIABLE APR_CPP_FLAGS) + EXEC_PROGRAM(${APU_CONFIG} ARGS "--cppflags" OUTPUT_VARIABLE APU_CPP_FLAGS) + + EXEC_PROGRAM(${APR_CONFIG} ARGS "--ldflags --libs --link-ld" OUTPUT_VARIABLE APR_EXTRA_LIBFLAGS) + EXEC_PROGRAM(${APU_CONFIG} ARGS "--ldflags --libs --link-ld" OUTPUT_VARIABLE APU_EXTRA_LIBFLAGS) + + CHECK_INCLUDE_FILES(execinfo.h HAS_BACKTRACE_H) + +ENDIF (UNIX) + +#search libaries for Windows +IF (WIN32) + + # search for pathes + FIND_PATH (SUBVERSION_BIN_DIR svn.exe + "$ENV{ProgramFiles}/Subversion/bin" + ) + + FIND_PATH (SUBVERSION_INCLUDE_DIR svn_client.h + "$ENV{ProgramFiles}/Subversion/include" + ) + + FIND_PATH(APR_INCLUDE_DIR apr.h + "$ENV{ProgramFiles}/Subversion/include/apr" + ) + + FIND_PATH(APU_INCLUDE_DIR apu.h + "$ENV{ProgramFiles}/Subversion/include/apr-util" + ) + + # search for libraries + FIND_LIBRARY(APR_LIB libapr + "$ENV{ProgramFiles}/Subversion/lib/apr" + ) + + FIND_LIBRARY(APRICONV_LIB libapriconv + "$ENV{ProgramFiles}/Subversion/lib/apr-iconv" + ) + + FIND_LIBRARY(APU_LIB libaprutil + "$ENV{ProgramFiles}/Subversion/lib/apr-util" + ) + + FIND_LIBRARY(APU_XMLLIB xml + "$ENV{ProgramFiles}/Subversion/lib/apr-util" + ) + + FIND_LIBRARY(NEON_LIB libneon + "$ENV{ProgramFiles}/Subversion/lib/neon" + ) + + FIND_LIBRARY(NEON_ZLIBSTATLIB zlibstat + "$ENV{ProgramFiles}/Subversion/lib/neon" + ) + + FIND_LIBRARY(INTL3LIB intl3_svn + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(DB44_LIB libdb44 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_CLIENTLIB libsvn_client-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_DELTALIB libsvn_delta-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_DIFFLIB libsvn_diff-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_FSBASELIB libsvn_fs_base-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_FSFSLIB libsvn_fs_fs-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_FSUTILLIB libsvn_fs_util-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_FSLIB libsvn_fs-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_RALOCALLIB libsvn_ra_local-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_RANEONLIB libsvn_ra_neon-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_RASVNLIB libsvn_ra_svn-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_RALIB libsvn_ra-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_REPOSITORYLIB libsvn_repos-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_SUBRLIB libsvn_subr-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + FIND_LIBRARY(SUBVERSION_WCLIB libsvn_wc-1 + "$ENV{ProgramFiles}/Subversion/lib" + ) + + SET(APR_EXTRA_LIBFLAGS ) + SET(APU_EXTRA_LIBFLAGS ) + + + # check found libraries + if (NOT APR_LIB) + MESSAGE(SEND_ERROR "No apr lib found!") + ELSE (NOT APR_LIB) + MESSAGE(STATUS "Found apr lib: ${APR_LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${APR_LIB}) + endif(NOT APR_LIB) + + if (NOT APRICONV_LIB) + MESSAGE(SEND_ERROR "No apriconv lib found!") + ELSE (NOT APRICONV_LIB) + MESSAGE(STATUS "Found apriconv lib: ${APRICONV_LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${APRICONV_LIB}) + endif(NOT APRICONV_LIB) + + if (NOT APU_LIB) + MESSAGE(SEND_ERROR "No aprutil lib found!") + ELSE (NOT APU_LIB) + MESSAGE(STATUS "Found aprutil lib: ${APU_LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${APU_LIB}) + endif(NOT APU_LIB) + + if (NOT APU_XMLLIB) + MESSAGE(SEND_ERROR "No xml lib found!") + ELSE (NOT APU_XMLLIB) + MESSAGE(STATUS "Found xml lib: ${APU_XMLLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${APU_XMLLIB}) + endif(NOT APU_XMLLIB) + + if (NOT NEON_LIB) + MESSAGE(SEND_ERROR "No neon lib found!") + ELSE (NOT NEON_LIB) + MESSAGE(STATUS "Found neon lib: ${NEON_LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${NEON_LIB}) + endif(NOT NEON_LIB) + + if (NOT NEON_ZLIBSTATLIB) + MESSAGE(SEND_ERROR "No zlibstat lib found!") + ELSE (NOT APRICONV_LIB) + MESSAGE(STATUS "Found zlibstat lib: ${NEON_ZLIBSTATLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${NEON_ZLIBSTATLIB}) + endif(NOT NEON_ZLIBSTATLIB) + + if (NOT INTL3LIB) + MESSAGE(SEND_ERROR "No intl3 lib found!") + ELSE (NOT INTL3LIB) + MESSAGE(STATUS "Found intl3 lib: ${INTL3LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${INTL3LIB}) + endif(NOT INTL3LIB) + + if (NOT DB44_LIB) + MESSAGE(SEND_ERROR "No db44 lib found!") + ELSE (NOT DB44_LIB) + MESSAGE(STATUS "Found db44 lib: ${DB44_LIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${DB44_LIB}) + endif(NOT DB44_LIB) + + if (NOT SUBVERSION_DELTALIB) + MESSAGE(SEND_ERROR "No subversion delta lib found!") + ELSE (NOT SUBVERSION_DELTALIB) + MESSAGE(STATUS "Found subversion delta lib: ${SUBVERSION_DELTALIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_DELTALIB}) + endif(NOT SUBVERSION_DELTALIB) + + if (NOT SUBVERSION_FSBASELIB) + MESSAGE(SEND_ERROR "No subversion fs base lib found!") + ELSE (NOT SUBVERSION_FSBASELIB) + MESSAGE(STATUS "Found subversion fs base lib: ${SUBVERSION_FSBASELIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_FSBASELIB}) + endif(NOT SUBVERSION_FSBASELIB) + + if (NOT SUBVERSION_FSFSLIB) + MESSAGE(SEND_ERROR "No subversion fs fs lib found!") + ELSE (NOT SUBVERSION_FSFSLIB) + MESSAGE(STATUS "Found subversion fs fs lib: ${SUBVERSION_FSFSLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_FSFSLIB}) + endif(NOT SUBVERSION_FSFSLIB) + + if (NOT SUBVERSION_FSUTILLIB) + MESSAGE(SEND_ERROR "No subversion fs util lib found!") + ELSE (NOT SUBVERSION_FSUTILLIB) + MESSAGE(STATUS "Found subversion fs util lib: ${SUBVERSION_FSUTILLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_FSUTILLIB}) + endif(NOT SUBVERSION_FSUTILLIB) + + if (NOT SUBVERSION_RALOCALLIB) + MESSAGE(SEND_ERROR "No subversion ra local lib found!") + ELSE (NOT SUBVERSION_RALOCALLIB) + MESSAGE(STATUS "Found subversion ra local lib: ${SUBVERSION_RALOCALLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_RALOCALLIB}) + endif(NOT SUBVERSION_RALOCALLIB) + + if (NOT SUBVERSION_RANEONLIB) + MESSAGE(SEND_ERROR "No subversion ra neon lib found!") + ELSE (NOT SUBVERSION_RANEONLIB) + MESSAGE(STATUS "Found subversion ra neon lib: ${SUBVERSION_RANEONLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_RANEONLIB}) + endif(NOT SUBVERSION_RANEONLIB) + + if (NOT SUBVERSION_RASVNLIB) + MESSAGE(SEND_ERROR "No subversion ra svn lib found!") + ELSE (NOT SUBVERSION_RASVNLIB) + MESSAGE(STATUS "Found subversion ra svn lib: ${SUBVERSION_RASVNLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_RASVNLIB}) + endif(NOT SUBVERSION_RASVNLIB) + +ENDIF (WIN32) + + +IF(NOT SUBVERSION_INCLUDE_DIR) + MESSAGE(SEND_ERROR "No subversion includes found!") +ELSE(NOT SUBVERSION_INCLUDE_DIR) + MESSAGE(STATUS "Found subversion include: ${SUBVERSION_INCLUDE_DIR}") +ENDIF(NOT SUBVERSION_INCLUDE_DIR) + +if (NOT SUBVERSION_CLIENTLIB) + MESSAGE(SEND_ERROR "No subversion client libs found!") +ELSE (NOT SUBVERSION_CLIENTLIB) + MESSAGE(STATUS "Found subversion client lib: ${SUBVERSION_CLIENTLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_CLIENTLIB}) +endif(NOT SUBVERSION_CLIENTLIB) + +if (NOT SUBVERSION_DIFFLIB) + MESSAGE(SEND_ERROR "No subversion diff lib found!") +ELSE (NOT SUBVERSION_DIFFLIB) + MESSAGE(STATUS "Found subversion diff lib: ${SUBVERSION_DIFFLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_DIFFLIB}) +endif(NOT SUBVERSION_DIFFLIB) + +if (NOT SUBVERSION_FSLIB) + MESSAGE(SEND_ERROR "No subversion fs lib found!") +ELSE (NOT SUBVERSION_FSLIB) + MESSAGE(STATUS "Found subversion fs lib: ${SUBVERSION_FSLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_FSLIB}) +endif(NOT SUBVERSION_FSLIB) + +if (NOT SUBVERSION_RALIB) + MESSAGE(SEND_ERROR "No subversion ra lib found!") +ELSE (NOT SUBVERSION_RALIB) + MESSAGE(STATUS "Found subversion ra lib: ${SUBVERSION_RALIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_RALIB}) +endif(NOT SUBVERSION_RALIB) + +if (NOT SUBVERSION_REPOSITORYLIB) + MESSAGE(SEND_ERROR "No subversion repository lib found!") +ELSE (NOT SUBVERSION_REPOSITORYLIB) + MESSAGE(STATUS "Found subversion repository lib: ${SUBVERSION_REPOSITORYLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_REPOSITORYLIB}) +endif(NOT SUBVERSION_REPOSITORYLIB) + +if (NOT SUBVERSION_SUBRLIB) + MESSAGE(SEND_ERROR "No subversion subr lib found!") +ELSE (NOT SUBVERSION_SUBRLIB) + MESSAGE(STATUS "Found subversion subr lib: ${SUBVERSION_SUBRLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_SUBRLIB}) +endif(NOT SUBVERSION_SUBRLIB) + +if (NOT SUBVERSION_WCLIB) + MESSAGE(SEND_ERROR "No subversion wc lib found!") +ELSE (NOT SUBVERSION_WCLIB) + MESSAGE(STATUS "Found subversion wc lib: ${SUBVERSION_WCLIB}") + SET(SUBVERSION_ALL_LIBS ${SUBVERSION_ALL_LIBS} ${SUBVERSION_WCLIB}) +endif(NOT SUBVERSION_WCLIB) + + +SET(SUBVERSIONFOUND true) diff --git a/src/svnqt/commititem.cpp b/src/svnqt/commititem.cpp new file mode 100644 index 0000000..2d97e6c --- /dev/null +++ b/src/svnqt/commititem.cpp @@ -0,0 +1,167 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "commititem.hpp" + +#include <svn_client.h> +#include <svn_props.h> + +namespace svn { + +CommitItem::CommitItem(const svn_client_commit_item_t*_item) +{ + init(); + if (_item) { + m_Path = QString::FROMUTF8(_item->path); + m_Kind = _item->kind; + m_Url = QString::FROMUTF8(_item->url); + if (_item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY) { + m_CopyFromRevision = _item->revision; + } else { + m_Revision = _item->revision; + } + m_CopyFromUrl = QString::FROMUTF8(_item->copyfrom_url); + m_State = _item->state_flags; + convertprop(_item->wcprop_changes); + } +} + +CommitItem::CommitItem(const svn_client_commit_item2_t*_item) +{ + init(); + + if (_item) { + m_Path = QString::FROMUTF8(_item->path); + m_Kind = _item->kind; + m_Url = QString::FROMUTF8(_item->url); + m_Revision = _item->revision; + m_CopyFromRevision = _item->copyfrom_rev; + m_CopyFromUrl = QString::FROMUTF8(_item->copyfrom_url); + m_State = _item->state_flags; + convertprop(_item->wcprop_changes); + } +} + +CommitItem::CommitItem(const svn_client_commit_item3_t*_item) +{ + init(); + + if (_item) { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + m_Path = QString::FROMUTF8(_item->path); + m_Kind = _item->kind; + m_Url = QString::FROMUTF8(_item->url); + m_Revision = _item->revision; + m_CopyFromRevision = _item->copyfrom_rev; + m_CopyFromUrl = QString::FROMUTF8(_item->copyfrom_url); + m_State = _item->state_flags; + convertprop(_item->incoming_prop_changes); + if (_item->outgoing_prop_changes) + { + convertprop(_item->outgoing_prop_changes); + } +#endif + } +} + +void CommitItem::convertprop(apr_array_header_t * list) +{ + if (!list) { + m_CommitProperties.clear(); + return; + } + for (int j = 0; j < list->nelts; ++j) { + svn_prop_t * item = ((svn_prop_t **)list->elts)[j]; + if (!item) continue; + m_CommitProperties[QString::FROMUTF8(item->name)]=QString::FROMUTF8(item->value->data,item->value->len); + } +} + +void CommitItem::init() +{ + m_Path=m_Url=m_CopyFromUrl = QString::null; + m_Kind = svn_node_unknown; + m_Revision=m_CopyFromRevision = -1; + m_State = 0; + m_CommitProperties.clear(); +} + +CommitItem::~CommitItem() +{ +} + +const QString& CommitItem::path()const +{ + return m_Path; +} + +const QString& CommitItem::url()const +{ + return m_Url; +} + +const QString& CommitItem::copyfromurl()const +{ + return m_CopyFromUrl; +} + +const PropertiesMap& CommitItem::properties()const +{ + return m_CommitProperties; +} + +svn_revnum_t CommitItem::revision()const +{ + return m_Revision; +} + +svn_revnum_t CommitItem::copyfromrevision()const +{ + return m_CopyFromRevision; +} + +svn_node_kind_t CommitItem::kind()const +{ + return m_Kind; +} + +apr_byte_t CommitItem::state()const +{ + return m_State; +} + +char CommitItem::actionType()const +{ + char r=0; + if (m_State & SVN_CLIENT_COMMIT_ITEM_IS_COPY) { + r = 'C'; + } else if (m_State & SVN_CLIENT_COMMIT_ITEM_ADD){ + r = 'A'; + } else if (m_State & SVN_CLIENT_COMMIT_ITEM_DELETE){ + r = 'D'; + } else if (m_State & SVN_CLIENT_COMMIT_ITEM_PROP_MODS || + m_State & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS){ + r = 'M'; + } else if (m_State & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN){ + r = 'L'; + } + return r; +} + +} diff --git a/src/svnqt/commititem.hpp b/src/svnqt/commititem.hpp new file mode 100644 index 0000000..fc12def --- /dev/null +++ b/src/svnqt/commititem.hpp @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNCOMMITITEM_H +#define SVNCOMMITITEM_H + +#include "client.hpp" + +#include <svn_types.h> +#include <apr.h> + +// forward declarations +struct svn_client_commit_item_t; +// only used if build against svn 1.3 api +struct svn_client_commit_item2_t; +// only used if build against svn 1.5 api +struct svn_client_commit_item3_t; + +namespace svn { + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class SVNQT_EXPORT CommitItem{ + +private: + void init(); + void convertprop(apr_array_header_t *); + +protected: + PropertiesMap m_CommitProperties; + QString m_Path,m_Url,m_CopyFromUrl; + svn_node_kind_t m_Kind; + svn_revnum_t m_Revision,m_CopyFromRevision; + apr_byte_t m_State; + +public: + //! constructor + CommitItem(const svn_client_commit_item_t*aSource=0); + //! constructor + /*! + * This one will only do something if build against subversion 1.3 + */ + CommitItem(const svn_client_commit_item2_t*); + /*! + * This one will only do something if build against subversion 1.5 + */ + CommitItem(const svn_client_commit_item3_t*); + //! Destructor + /*! + * Not virtual 'cause no child class is needed + */ + ~CommitItem(); + + const QString& path()const; + const QString& url()const; + const QString& copyfromurl()const; + const PropertiesMap& properties()const; + svn_revnum_t revision()const; + svn_revnum_t copyfromrevision()const; + svn_node_kind_t kind()const; + apr_byte_t state()const; + //! Kind of action + /*! + * \return Char for type of action or 0 if unknown. Currently known is + * <UL> + * <LI>A - add</LI> + * <LI>C - copy</LI> + * <LI>D - deletion</LI> + * <LI>M - Modify (content or property)</LI> + * <LI>R - replaced</LI> + * <LI>L - (un-)lock</LI> + * </UL> + */ + char actionType()const; +}; + +#if QT_VERSION < 0x040000 + typedef QValueList<CommitItem> CommitItemList; +#else + typedef QList<CommitItem> CommitItemList; +#endif +} + +#endif diff --git a/src/svnqt/conflictdescription.cpp b/src/svnqt/conflictdescription.cpp new file mode 100644 index 0000000..bbf059a --- /dev/null +++ b/src/svnqt/conflictdescription.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "conflictdescription.hpp" +#include "svnqt_defines.hpp" + +#include <svn_wc.h> + +namespace svn { + +ConflictDescription::ConflictDescription() + :m_pool() +{ + init(); +} + + +ConflictDescription::~ConflictDescription() +{ +} + +ConflictDescription::ConflictDescription(const svn_wc_conflict_description_t*conflict) + :m_pool() +{ + init(); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + if (!conflict) { + return; + } + m_baseFile=QString::FROMUTF8(conflict->base_file); + m_mergedFile=QString::FROMUTF8(conflict->merged_file); + m_mimeType=QString::FROMUTF8(conflict->mime_type); + m_myFile=QString::FROMUTF8(conflict->my_file); + m_Path=QString::FROMUTF8(conflict->path); + m_propertyName=QString::FROMUTF8(conflict->property_name); + m_theirFile=QString::FROMUTF8(conflict->their_file); + switch(conflict->action) { + case svn_wc_conflict_action_edit: + m_action=ConflictEdit; + break; + case svn_wc_conflict_action_add: + m_action=ConflictAdd; + break; + case svn_wc_conflict_action_delete: + m_action=ConflictDelete; + break; + } + switch (conflict->kind) { + case svn_wc_conflict_kind_text: + m_Type=ConflictText; + break; + case svn_wc_conflict_kind_property: + m_Type=ConflictProperty; + break; + } + m_nodeKind=conflict->node_kind; + m_binary=conflict->is_binary; + switch (conflict->reason) { + case svn_wc_conflict_reason_edited: + m_reason=ReasonEdited; + break; + case svn_wc_conflict_reason_obstructed: + m_reason=ReasonObstructed; + break; + case svn_wc_conflict_reason_deleted: + m_reason=ReasonDeleted; + break; + case svn_wc_conflict_reason_missing: + m_reason=ReasonMissing; + break; + case svn_wc_conflict_reason_unversioned: + m_reason=ReasonUnversioned; + break; + } +#else + Q_UNUSED(conflict); +#endif +} + +ConflictDescription::ConflictDescription(const ConflictDescription&) + :m_pool() +{ +} + +} + +svn::ConflictDescription::ConflictAction svn::ConflictDescription::action() const +{ + return m_action; +} + +const QString&svn::ConflictDescription::baseFile() const +{ + return m_baseFile; +} + + +/*! + \fn svn::ConflictDescription::init() + */ +void svn::ConflictDescription::init() +{ + m_baseFile=m_Path=m_mergedFile=m_propertyName=m_theirFile=m_myFile=m_mimeType=QString::null; + m_action=ConflictEdit; + m_Type=ConflictText; + m_reason=ReasonEdited; + m_binary=false; + m_nodeKind = svn_node_unknown; +} + + +bool svn::ConflictDescription::binary() const +{ + return m_binary; +} + + +const QString& svn::ConflictDescription::mergedFile() const +{ + return m_mergedFile; +} + + +const QString& svn::ConflictDescription::mimeType() const +{ + return m_mimeType; +} + + +const QString& svn::ConflictDescription::myFile() const +{ + return m_myFile; +} + + +svn_node_kind_t svn::ConflictDescription::nodeKind() const +{ + return m_nodeKind; +} + + +const QString& svn::ConflictDescription::Path() const +{ + return m_Path; +} + + +const QString& svn::ConflictDescription::propertyName() const +{ + return m_propertyName; +} + + +svn::ConflictDescription::ConflictReason svn::ConflictDescription::reason() const +{ + return m_reason; +} + + +const QString& svn::ConflictDescription::theirFile() const +{ + return m_theirFile; +} + + +svn::ConflictDescription::ConflictType svn::ConflictDescription::Type() const +{ + return m_Type; +} diff --git a/src/svnqt/conflictdescription.hpp b/src/svnqt/conflictdescription.hpp new file mode 100644 index 0000000..3f72562 --- /dev/null +++ b/src/svnqt/conflictdescription.hpp @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNCONFLICTDESCRIPTION_H +#define SVNCONFLICTDESCRIPTION_H + +struct svn_wc_conflict_description_t; + +#include "svnqt/pool.hpp" +#include "svnqt/svnqt_defines.hpp" +#include <svn_types.h> + +#include <qstring.h> + +namespace svn { + +/** Wrapper for svn_wc_conflict_description_t + * does nothing when build against subversion prior 1.5 + * @since subversion 1.5 + * @author Rajko Albrecht +*/ +class SVNQT_EXPORT ConflictDescription +{ +public: + enum ConflictType { + ConflictText, + ConflictProperty + }; + enum ConflictReason { + ReasonEdited, + ReasonObstructed, + ReasonDeleted, + ReasonMissing, + ReasonUnversioned + }; + enum ConflictAction { + ConflictEdit, + ConflictAdd, + ConflictDelete + }; + ConflictDescription(); + ConflictDescription(const svn_wc_conflict_description_t*); + ~ConflictDescription(); + + ConflictAction action() const; + ConflictType Type() const; + ConflictReason reason() const; + svn_node_kind_t nodeKind() const; + bool binary() const; + const QString& baseFile() const; + const QString& theirFile() const; + const QString& propertyName() const; + const QString& Path() const; + const QString& myFile() const; + const QString& mimeType() const; + const QString& mergedFile() const; + +protected: + //! don't use it. + ConflictDescription(const ConflictDescription&); + void init(); +protected: + Pool m_pool; + bool m_binary; + ConflictAction m_action; + ConflictType m_Type; + ConflictReason m_reason; + QString m_baseFile; + QString m_mergedFile; + QString m_mimeType; + QString m_myFile; + QString m_Path; + QString m_propertyName; + QString m_theirFile; + svn_node_kind_t m_nodeKind; +}; + +} + +#endif diff --git a/src/svnqt/conflictresult.cpp b/src/svnqt/conflictresult.cpp new file mode 100644 index 0000000..0465e33 --- /dev/null +++ b/src/svnqt/conflictresult.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "conflictresult.hpp" + +#include "svnqt_defines.hpp" + +#include <svn_wc.h> + +namespace svn +{ + ConflictResult::ConflictResult() + :m_choice(ChooseMerged),m_MergedFile(QString::null) + { + } + + ConflictResult::ConflictResult(const svn_wc_conflict_result_t*aResult) + { + if (!aResult){ + return; + } +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + switch (aResult->choice){ + case svn_wc_conflict_choose_base: + m_choice=ChooseBase; + break; + case svn_wc_conflict_choose_theirs_full: + m_choice=ChooseTheirsFull; + break; + case svn_wc_conflict_choose_mine_full: + m_choice=ChooseMineFull; + break; + case svn_wc_conflict_choose_theirs_conflict: + m_choice=ChooseTheirsConflict; + break; + case svn_wc_conflict_choose_mine_conflict: + m_choice=ChooseMineConflict; + break; + case svn_wc_conflict_choose_merged: + m_choice=ChooseMerged; + break; + case svn_wc_conflict_choose_postpone: + default: + m_choice=ChoosePostpone; + break; + } + if (aResult->merged_file) { + m_MergedFile=QString::FROMUTF8(aResult->merged_file); + } else { + m_MergedFile=QString::null; + } +#else + Q_UNUSED(aResult); +#endif + } + + void ConflictResult::setMergedFile(const QString&aMergedfile) { + m_MergedFile=aMergedfile; + } + + void ConflictResult::setChoice(ConflictChoice aValue) + { + m_choice=aValue; + } + + void ConflictResult::assignResult(svn_wc_conflict_result_t**aResult,const Pool&pool)const + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + svn_wc_conflict_choice_t _choice; + switch (choice()) { + case ConflictResult::ChooseBase: + _choice=svn_wc_conflict_choose_base; + break; + case ConflictResult::ChooseTheirsFull: + _choice=svn_wc_conflict_choose_theirs_full; + break; + case ConflictResult::ChooseMineFull: + _choice=svn_wc_conflict_choose_mine_full; + break; + case ConflictResult::ChooseTheirsConflict: + _choice=svn_wc_conflict_choose_theirs_conflict; + break; + case ConflictResult::ChooseMineConflict: + _choice=svn_wc_conflict_choose_mine_conflict; + break; + case ConflictResult::ChooseMerged: + _choice=svn_wc_conflict_choose_merged; + break; + case ConflictResult::ChoosePostpone: + default: + _choice=svn_wc_conflict_choose_postpone; + break; + + } + const char* _merged_file = mergedFile().isNull()?0:apr_pstrdup (pool,mergedFile().TOUTF8()); + if ((*aResult)==0) { + (*aResult) = svn_wc_create_conflict_result(_choice,_merged_file,pool); + } else { + (*aResult)->choice=_choice; + (*aResult)->merged_file=_merged_file; + } +#else + Q_UNUSED(aResult); + Q_UNUSED(pool); +#endif + } + + const svn_wc_conflict_result_t*ConflictResult::result(const Pool&pool)const + { + svn_wc_conflict_result_t*result=0; + assignResult(&result,pool); + return result; + } +} diff --git a/src/svnqt/conflictresult.hpp b/src/svnqt/conflictresult.hpp new file mode 100644 index 0000000..0dfb426 --- /dev/null +++ b/src/svnqt/conflictresult.hpp @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _CONFLICT_RESULT_HPP +#define _CONFLICT_RESULT_HPP + +struct svn_wc_conflict_result_t; + +#include "svnqt/pool.hpp" +#include "svnqt/svnqt_defines.hpp" +#include <svn_types.h> + +#include <qstring.h> + +namespace svn { + +class SVNQT_EXPORT ConflictResult +{ + public: + enum ConflictChoice { + //! let user make a call to resolve + ChoosePostpone, + ChooseBase, + ChooseTheirsFull, + ChooseMineFull, + ChooseTheirsConflict, + ChooseMineConflict, + ChooseMerged + }; + ConflictResult(); + //! Copy constructor + /*! only usefull wenn build with subversion 1.5 or newer + */ + ConflictResult(const svn_wc_conflict_result_t*); + + const QString& mergedFile()const + { + return m_MergedFile; + } + void setMergedFile(const QString&aMergedfile); + + ConflictChoice choice()const + { + return m_choice; + } + void setChoice(ConflictChoice aValue); + + const svn_wc_conflict_result_t*result(const Pool&pool)const; + void assignResult(svn_wc_conflict_result_t**aResult,const Pool&pool)const; + + protected: + ConflictChoice m_choice; + //! Merged file + /*! will only used if m_choice is ChooseMerged + */ + QString m_MergedFile; +}; + +} + +#endif diff --git a/src/svnqt/context.cpp b/src/svnqt/context.cpp new file mode 100644 index 0000000..56f35c0 --- /dev/null +++ b/src/svnqt/context.cpp @@ -0,0 +1,136 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// Apache Portable Runtime +#include "apr_xlate.h" + +// Subversion api +#include "svn_auth.h" +#include "svn_config.h" +#include "svn_subst.h" +//#include "svn_utf.h" + +// svncpp +#include "apr.hpp" +#include "context.hpp" +#include "context_listener.hpp" +#include "contextdata.hpp" + +namespace svn +{ + Context::Context (const QString &configDir) + : ref_count() + { + m = new ContextData (configDir); + } + + Context::Context (const Context & src) + : ref_count() + { + m = new ContextData (src.m->configDir()); + setLogin (src.getUsername (), src.getPassword ()); + } + + Context::~Context () + { + delete m; + } + + void + Context::setAuthCache (bool value) + { + m->setAuthCache (value); + } + + void + Context::setLogin (const QString& username, const QString& password) + { + m->setLogin (username, password); + } + + Context::operator svn_client_ctx_t * () + { + return m->ctx(); + } + + svn_client_ctx_t * + Context::ctx () + { + return m->ctx(); + } + + void + Context::setLogMessage (const QString& msg) + { + m->setLogMessage (msg); + } + + const QString& + Context::getUsername () const + { + return m->getUsername (); + } + + const QString& + Context::getPassword () const + { + return m->getPassword (); + } + + const QString& + Context::getLogMessage () const + { + return m->getLogMessage (); + } + + void + Context::setListener (ContextListener * listener) + { + m->setListener(listener); + } + + ContextListener * + Context::getListener () const + { + return m->getListener(); + } + + void + Context::reset () + { + m->reset(); + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/context.hpp b/src/svnqt/context.hpp new file mode 100644 index 0000000..b45cb1c --- /dev/null +++ b/src/svnqt/context.hpp @@ -0,0 +1,176 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_CONTEXT_HPP_ +#define _SVNCPP_CONTEXT_HPP_ + +#include "svnqt/svnqt_defines.hpp" + +// qt +#include <qstring.h> + +// Subversion api +#include "svn_client.h" + +// svncpp +#include "svnqt/pool.hpp" +#include "svnqt/smart_pointer.hpp" + + +namespace svn +{ + // forward declarations + class ContextListener; + class ContextData; + + /** + * This class will hold the client context + * and replace the old notification and baton + * stuff + */ + class SVNQT_EXPORT Context:public ref_count + { + public: + /** + * default constructor + * + * @param configDir location where the + * subversion api stores its + * configuration + */ + Context (const QString & configDir=QString::null); + + /** + * copy constructor + * + * @param src + */ + Context (const Context &src); + + /** + * destructor + */ + virtual ~Context (); + + /** + * enable/disable authentication caching + * + * @param value true=enable/false=disable + */ + void setAuthCache (bool value); + + /** + * set username/password for authentication + */ + void setLogin (const QString& username, const QString& password); + + /** + * operator to get svn_client_ctx object + */ + operator svn_client_ctx_t * (); + + /** + * return the svn_client_ctx object + */ + svn_client_ctx_t * ctx (); + + /** + * this will be called at the beginning of an action. + * the log message will be reset. + */ + void reset (); + + /** + * set log message + * + * @param msg + */ + void setLogMessage (const QString& msg); + + /** + * get log message + * + * @return log message + */ + const QString& + getLogMessage () const; + + /** + * get username + * + * @return username + */ + const QString& + getUsername () const; + + /** + * get password + * + * @return password + */ + const QString& + getPassword () const; + + /** + * set the listener for the context. The listener will be + * called to poll authentication information and other + * information like this + * + * @param listener + */ + void + setListener (ContextListener * listener); + + /** + * get the listener + * + * @return the listener + */ + ContextListener * + getListener () const; + + private: + ContextData * m; + + /** + * disable assignment operator + */ + Context & operator = (const Context &); + }; + + typedef svn::smart_pointer<svn::Context> ContextP; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/context_listener.hpp b/src/svnqt/context_listener.hpp new file mode 100644 index 0000000..8383724 --- /dev/null +++ b/src/svnqt/context_listener.hpp @@ -0,0 +1,271 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_CONTEXT_LISTENER_HPP_ +#define _SVNCPP_CONTEXT_LISTENER_HPP_ + +// svncpp +#include "svnqt/pool.hpp" +#include "svnqt/commititem.hpp" +#include "svnqt/svnqt_defines.hpp" +// qt +#include <qstring.h> +// Subversion api +#include <svn_client.h> + + +namespace svn +{ + class ConflictResult; + class ConflictDescription; + /** + * This is the interface that is used by @a Context + * for callbacks. + * To use this you will have to inherit from this + * interface and overwrite the virtual methods. + */ + class SVNQT_EXPORT ContextListener + { + public: + /** + * empty destructor avoids a lot of compiler warnings + */ + virtual ~ContextListener(){} + /** + * this method will be called to retrieve + * authentication information. This will called until valid information were + * inserted or it returns false. + * + * @param username username set as default by subversion + * @param realm in which username/password will be used + * @param password target storage for password + * @param maySave in/out set false to not save + * @return continue action? + * @retval true continue + */ + virtual bool + contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave) = 0; + /** + * this method will be called to retrieve + * authentication information stored not by subversion. This + * will only called once! + * + * @param username username set as default by subversion + * @param realm in which username/password will be used + * @param password target storage for password + * @return continue action? should only in case of emergency return false. + * @retval true continue + */ + virtual bool + contextGetSavedLogin(const QString & realm, + QString & username, + QString & password) = 0; + /** + * this method will be called to retrieve + * authentication information stored not persistent. This + * will only called once! + * + * @param username username set as default by subversion + * @param realm in which username/password will be used + * @param password target storage for password + * @return continue action? should only in case of emergency return false. + * @retval true continue + */ + virtual bool + contextGetCachedLogin(const QString & realm, + QString & username, + QString & password) = 0; + + /** + * this method will be called to notify about + * the progress of an ongoing action + * + * @param path + * @param action + * @param kind + * @param mime_type + * @param content_state + * @param prop_state + * @param revision + */ + virtual void + contextNotify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision) = 0; + /** + * this method will be called to notify about + * the progress of an ongoing action + * + * @param action the action got notified about + * @since subversion 1.2 + */ + virtual void + contextNotify (const svn_wc_notify_t *action) = 0; + /** + * this method will be called periodically to allow + * the app to cancel long running operations + * + * @return cancel action? + * @retval true cancel + */ + virtual bool + contextCancel() = 0; + + /** + * this method will be called to retrieve + * a log message + * + * WORKAROUND FOR apr_xlate PROBLEM: + * STRINGS ALREADY HAVE TO BE UTF8!!! + * + * @param msg log message + * @return continue action? + * @retval true continue + */ + virtual bool + contextGetLogMessage (QString & msg,const CommitItemList&) = 0; + + typedef enum + { + DONT_ACCEPT = 0, + ACCEPT_TEMPORARILY, + ACCEPT_PERMANENTLY + } SslServerTrustAnswer; + + + /** + * @see contextSslServerTrust + * @see svn_auth_cred_ssl_server_trust_t + */ + struct SslServerTrustData + { + public: + /** bit coded failures */ + const apr_uint32_t failures; + + /** certificate information */ + QString hostname; + QString fingerprint; + QString validFrom; + QString validUntil; + QString issuerDName; + QString realm; + bool maySave; + + SslServerTrustData (const apr_uint32_t failures_) + : failures (failures_), hostname (""), fingerprint (""), + validFrom (""), validUntil (""), issuerDName (""), + realm (""), maySave (true) + { + } + }; + + + /** + * this method is called if there is ssl server + * information, that has to be confirmed by the user + * + * @param data + * @param acceptedFailures + * @return @a SslServerTrustAnswer + */ + virtual SslServerTrustAnswer + contextSslServerTrustPrompt (const SslServerTrustData & data, + apr_uint32_t & acceptedFailures) = 0; + + /** + * this method is called to retrieve client side + * information + */ + virtual bool + contextSslClientCertPrompt (QString & certFile) = 0; + + /** + * this method is called to retrieve the password + * for the client certificate + * + * @param password + * @param realm + * @param maySave + */ + virtual bool + contextSslClientCertPwPrompt (QString & password, + const QString & realm, + bool & maySave) = 0; + /** + * this method is called to retrieve the password + * for the client certificate from a local storage or such. it will called only once. + * + * @param password + * @param realm + */ + virtual bool + contextLoadSslClientCertPw(QString&password,const QString&realm)=0; + + virtual void + contextProgress(long long int current, long long int max) = 0; + + /** + * try to translate a text. In current implementation does + * nothing than returning the origin but may used to get an + * application specific translation. + * @param what text to translate + * @return translated text or origin. + */ + virtual QString translate(const QString&what){return what;} + + /** Callback for svn_wc_conflict_resolver_func_t in subversion 1.5 + * This method is only useful when build with subverion 1.5 or above. The default implementation sets + * result to ConflictResult::ChoosePostpone. Then conflicts while merge, update and switch results in an + * item with "conflict" status set. + * + * @param result The result where to store + * @param description description of conflict. + * @return true if result may used and operaion should continue. + * @sa svn_wc_conflict_description_t, svn_wc_conflict_result_t + * @since subversion 1.5 + */ + virtual bool contextConflictResolve(ConflictResult&result,const ConflictDescription&description); + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/contextdata.cpp b/src/svnqt/contextdata.cpp new file mode 100644 index 0000000..b4c2ea4 --- /dev/null +++ b/src/svnqt/contextdata.cpp @@ -0,0 +1,782 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "contextdata.hpp" +#include "context_listener.hpp" +#include "conflictresult.hpp" +#include "conflictdescription.hpp" + +#include <svn_config.h> +#include <svn_wc.h> + +namespace svn { + +ContextData::ContextData(const QString & configDir_) + : listener (0), logIsSet (false), + m_promptCounter (0), m_ConfigDir(configDir_) +{ + const char * c_configDir = 0; + if( m_ConfigDir.length () > 0 ) + { + c_configDir = m_ConfigDir.TOUTF8(); + } + + // make sure the configuration directory exists + svn_config_ensure (c_configDir, pool); + + // intialize authentication providers + // * simple + // * username + // * simple pw cache of frontend app + // * simple pw storage + // * simple prompt + // * ssl server trust file + // * ssl server trust prompt + // * ssl client cert pw file + // * ssl client cert pw load + // * ssl client cert pw prompt + // * ssl client cert file + // =================== + // 11 providers (+1 for windowsvariant) + + apr_array_header_t *providers = +#if defined(WIN32) && (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + apr_array_make (pool, 12, sizeof (svn_auth_provider_object_t *)); +#else + apr_array_make (pool, 11, sizeof (svn_auth_provider_object_t *)); +#endif + svn_auth_provider_object_t *provider; + +#if defined(WIN32) && (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_windows_simple_provider (&provider, pool); + APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; +#endif + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_simple_provider +#else + svn_client_get_simple_provider +#endif + (&provider, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_username_provider +#else + svn_client_get_username_provider +#endif + (&provider,pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_simple_prompt_provider +#else + svn_client_get_simple_prompt_provider +#endif + (&provider,onCachedPrompt,this,0,pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_simple_prompt_provider +#else + svn_client_get_simple_prompt_provider +#endif + (&provider,onSavedPrompt,this,0,pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_simple_prompt_provider +#else + svn_client_get_simple_prompt_provider +#endif + /* not very nice. should be infinite... */ + (&provider,onSimplePrompt,this,100000000,pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + + // add ssl providers + + // file first then prompt providers +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_server_trust_file_provider +#else + svn_client_get_ssl_server_trust_file_provider +#endif + (&provider, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_client_cert_file_provider +#else + svn_client_get_ssl_client_cert_file_provider +#endif + (&provider, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_client_cert_pw_file_provider +#else + svn_client_get_ssl_client_cert_pw_file_provider +#endif + (&provider, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_server_trust_prompt_provider +#else + svn_client_get_ssl_server_trust_prompt_provider +#endif + (&provider, onSslServerTrustPrompt, this, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + + // first try load from extra storage +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_client_cert_pw_prompt_provider +#else + svn_client_get_ssl_client_cert_pw_prompt_provider +#endif + (&provider, onFirstSslClientCertPw, this, 0, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + + // plugged in 3 as the retry limit - what is a good limit? +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + svn_auth_get_ssl_client_cert_pw_prompt_provider +#else + svn_client_get_ssl_client_cert_pw_prompt_provider +#endif + (&provider, onSslClientCertPwPrompt, this, 3, pool); + *(svn_auth_provider_object_t **)apr_array_push (providers) = provider; + + svn_auth_baton_t *ab; + svn_auth_open (&ab, providers, pool); + + // initialize ctx structure + svn_client_create_context(&m_ctx,pool); + + // get the config based on the configDir passed in + svn_config_get_config ( &(m_ctx->config), c_configDir, pool); + + // tell the auth functions where the config is + if (c_configDir) { + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_CONFIG_DIR, + c_configDir); + } + + m_ctx->auth_baton = ab; + m_ctx->notify_func = onNotify; + m_ctx->notify_baton = this; + m_ctx->cancel_func = onCancel; + m_ctx->cancel_baton = this; + m_ctx->notify_func2 = onNotify2; + m_ctx->notify_baton2 = this; + + m_ctx->log_msg_func = onLogMsg; + m_ctx->log_msg_baton = this; + // subversion 1.3 functions + m_ctx->log_msg_func2 = onLogMsg2; + m_ctx->log_msg_baton2 = this; + + m_ctx->progress_func = onProgress; + m_ctx->progress_baton = this; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) + m_ctx->log_msg_func3 = onLogMsg3; + m_ctx->log_msg_baton3 = this; + + m_ctx->conflict_func = onWcConflictResolver; + m_ctx->conflict_baton = this; + + m_ctx->client_name = "SvnQt wrapper client"; + initMimeTypes(); +#endif +} + + +ContextData::~ContextData() +{ +} + + +const QString&ContextData::getLogMessage () const +{ + return logMessage; +} + +bool ContextData::retrieveLogMessage (QString & msg,const CommitItemList&_itemlist) +{ + bool ok = false; + if (listener) { + ok = listener->contextGetLogMessage (logMessage,_itemlist); + if (ok) + msg = logMessage; + else + logIsSet = false; + } + return ok; +} + +void ContextData::notify(const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision) +{ + if (listener != 0) { + listener->contextNotify (path, action, kind, mime_type, + content_state, prop_state, revision); + } +} + +void ContextData::notify (const svn_wc_notify_t *action) +{ + if (listener != 0) { + listener->contextNotify(action); + } +} + +bool ContextData::cancel() +{ + if (listener != 0) { + return listener->contextCancel (); + } else { + // don't cancel if no listener + return false; + } +} +const QString& ContextData::getUsername () const +{ + return username; +} + +const QString& ContextData::getPassword() const +{ + return password; +} + +bool ContextData::retrieveLogin (const char * username_, + const char * realm, + bool &may_save) +{ + bool ok; + + if (listener == 0) + return false; + + username = QString::FROMUTF8(username_); + ok = listener->contextGetLogin(QString::FROMUTF8(realm),username, password, may_save); + + return ok; +} + +bool ContextData::retrieveSavedLogin (const char * username_, + const char * realm, + bool & may_save) +{ + bool ok; + may_save = false; + + if (listener == 0) + return false; + + username = QString::FROMUTF8(username_); + ok = listener->contextGetSavedLogin(QString::FROMUTF8(realm),username, password); + return ok; +} + +bool ContextData::retrieveCachedLogin (const char * username_, + const char * realm, + bool & may_save) +{ + bool ok; + may_save = false; + + if (listener == 0) + return false; + + username = QString::FROMUTF8(username_); + ok = listener->contextGetCachedLogin(QString::FROMUTF8(realm),username, password); + return ok; +} + +svn_client_ctx_t *ContextData::ctx() +{ + return m_ctx; +} + +const QString&ContextData::configDir()const +{ + return m_ConfigDir; +} + +svn_error_t * +ContextData::getContextData (void * baton, ContextData ** data) +{ + if (baton == NULL) + return svn_error_create (SVN_ERR_CANCELLED, NULL, + "invalid baton"); + + ContextData * data_ = static_cast <ContextData*>(baton); + + if (data_->listener == 0) + return svn_error_create (SVN_ERR_CANCELLED, NULL, + "invalid listener"); + + *data = data_; + return SVN_NO_ERROR; +} + +void ContextData::setAuthCache(bool value) +{ + void *param = 0; + if (!value) { + param = (void *)"1"; + } + svn_auth_set_parameter (m_ctx->auth_baton, + SVN_AUTH_PARAM_NO_AUTH_CACHE,param); +} + +void ContextData::setLogin(const QString& usr, const QString& pwd) +{ + username = usr; + password = pwd; + svn_auth_baton_t * ab = m_ctx->auth_baton; + svn_auth_set_parameter (ab, SVN_AUTH_PARAM_DEFAULT_USERNAME, username.TOUTF8()); + svn_auth_set_parameter (ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD, password.TOUTF8()); +} + +void ContextData::setLogMessage (const QString& msg) +{ + logMessage = msg; + if (msg.isNull()) { + logIsSet = false; + } else { + logIsSet = true; + } +} + +svn_error_t *ContextData::onLogMsg (const char **log_msg, + const char **tmp_file, + apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString msg; + if (data->logIsSet) { + msg = data->getLogMessage (); + } else { + CommitItemList _items; + for (int j = 0; j < commit_items->nelts; ++j) { + svn_client_commit_item_t*item = ((svn_client_commit_item_t **)commit_items->elts)[j]; + _items.push_back(CommitItem(item)); + } + if (!data->retrieveLogMessage (msg,_items)) { + return data->generate_cancel_error(); + } + } + + *log_msg = apr_pstrdup (pool,msg.TOUTF8()); + *tmp_file = NULL; + return SVN_NO_ERROR; +} + +svn_error_t *ContextData::onLogMsg2 (const char **log_msg, + const char **tmp_file, + const apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString msg; + if (data->logIsSet) { + msg = data->getLogMessage (); + } else { + CommitItemList _items; + for (int j = 0; j < commit_items->nelts; ++j) { + svn_client_commit_item2_t*item = ((svn_client_commit_item2_t **)commit_items->elts)[j]; + _items.push_back(CommitItem(item)); + } + + if (!data->retrieveLogMessage (msg,_items)) { + return data->generate_cancel_error(); + } + } + + *log_msg = apr_pstrdup (pool,msg.TOUTF8()); + *tmp_file = NULL; + return SVN_NO_ERROR; +} + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) +svn_error_t *ContextData::onLogMsg3 (const char **log_msg, + const char **tmp_file, + const apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString msg; + if (data->logIsSet) { + msg = data->getLogMessage (); + } else { + CommitItemList _items; + for (int j = 0; j < commit_items->nelts; ++j) { + svn_client_commit_item3_t*item = ((svn_client_commit_item3_t **)commit_items->elts)[j]; + _items.push_back(CommitItem(item)); + } + + if (!data->retrieveLogMessage (msg,_items)) { + return data->generate_cancel_error(); + } + } + + *log_msg = apr_pstrdup (pool,msg.TOUTF8()); + *tmp_file = NULL; + return SVN_NO_ERROR; +} +#endif + +void ContextData::onNotify (void * baton, + const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision) +{ + if (baton == 0) + return; + ContextData * data = static_cast <ContextData *> (baton); + data->notify (path, action, kind, mime_type, content_state, + prop_state, revision); +} + +void ContextData::onNotify2(void*baton,const svn_wc_notify_t *action,apr_pool_t */*tpool*/) +{ + if (!baton) return; + ContextData * data = static_cast <ContextData *> (baton); + data->notify (action); +} + +svn_error_t * ContextData::onCancel (void * baton) +{ + if (baton == 0) return SVN_NO_ERROR; + ContextData * data = static_cast <ContextData *> (baton); + if( data->cancel () ) + return data->generate_cancel_error(); + else + return SVN_NO_ERROR; +} + +svn_error_t *ContextData::onCachedPrompt(svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + bool may_save = _may_save != 0; + if (!data->retrieveCachedLogin (username, realm, may_save )) + return SVN_NO_ERROR; + svn_auth_cred_simple_t* lcred = (svn_auth_cred_simple_t*) + apr_palloc (pool, sizeof (svn_auth_cred_simple_t)); + QByteArray l; + l = data->getPassword().TOUTF8(); + lcred->password = apr_pstrndup (pool,l,l.size()); + l = data->getUsername().TOUTF8(); + lcred->username = apr_pstrndup (pool,l,l.size()); + + // tell svn if the credentials need to be saved + lcred->may_save = may_save; + *cred = lcred; + + return SVN_NO_ERROR; +} + +svn_error_t *ContextData::onSavedPrompt(svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + bool may_save = _may_save != 0; + if (!data->retrieveSavedLogin (username, realm, may_save )) + return SVN_NO_ERROR; + svn_auth_cred_simple_t* lcred = (svn_auth_cred_simple_t*) + apr_palloc (pool, sizeof (svn_auth_cred_simple_t)); + QByteArray l; + l = data->getPassword().TOUTF8(); + lcred->password = apr_pstrndup (pool,l,l.size()); + l = data->getUsername().TOUTF8(); + lcred->username = apr_pstrndup (pool,l,l.size()); + + // tell svn if the credentials need to be saved + lcred->may_save = may_save; + *cred = lcred; + + return SVN_NO_ERROR; +} + +svn_error_t *ContextData::onSimplePrompt (svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + bool may_save = _may_save != 0; + if (!data->retrieveLogin (username, realm, may_save )) + return data->generate_cancel_error(); + + svn_auth_cred_simple_t* lcred = (svn_auth_cred_simple_t*) + apr_palloc (pool, sizeof (svn_auth_cred_simple_t)); + QByteArray l; + l = data->getPassword().TOUTF8(); + lcred->password = apr_pstrndup (pool,l,l.size()); + l = data->getUsername().TOUTF8(); + lcred->username = apr_pstrndup (pool,l,l.size()); + + // tell svn if the credentials need to be saved + lcred->may_save = may_save; + *cred = lcred; + + return SVN_NO_ERROR; +} + +svn_error_t * ContextData::onSslServerTrustPrompt (svn_auth_cred_ssl_server_trust_t **cred, + void *baton, + const char *realm, + apr_uint32_t failures, + const svn_auth_ssl_server_cert_info_t *info, + svn_boolean_t may_save, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + ContextListener::SslServerTrustData trustData (failures); + if (realm != NULL) + trustData.realm = realm; + trustData.hostname = info->hostname; + trustData.fingerprint = info->fingerprint; + trustData.validFrom = info->valid_from; + trustData.validUntil = info->valid_until; + trustData.issuerDName = info->issuer_dname; + trustData.maySave = may_save != 0; + + apr_uint32_t acceptedFailures = failures; + ContextListener::SslServerTrustAnswer answer = + data->listener->contextSslServerTrustPrompt ( + trustData, acceptedFailures ); + + if(answer == ContextListener::DONT_ACCEPT) { + *cred = 0L; + } else + { + svn_auth_cred_ssl_server_trust_t *cred_ = + (svn_auth_cred_ssl_server_trust_t*) + apr_palloc (pool, sizeof (svn_auth_cred_ssl_server_trust_t)); + + cred_->accepted_failures = failures; + if (answer == ContextListener::ACCEPT_PERMANENTLY) + { + cred_->may_save = true; + } else { + cred_->may_save = false; + } + *cred = cred_; + } + + return SVN_NO_ERROR; +} + +svn_error_t * ContextData::onSslClientCertPrompt (svn_auth_cred_ssl_client_cert_t **cred, + void *baton, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString certFile; + if (!data->listener->contextSslClientCertPrompt (certFile)) + return data->generate_cancel_error(); + + svn_auth_cred_ssl_client_cert_t *cred_ = + (svn_auth_cred_ssl_client_cert_t*) + apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_t)); + + cred_->cert_file = certFile.TOUTF8(); + + *cred = cred_; + return SVN_NO_ERROR; +} + +svn_error_t *ContextData::onFirstSslClientCertPw ( + svn_auth_cred_ssl_client_cert_pw_t **cred, + void *baton, + const char *realm, + svn_boolean_t maySave, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString password; + bool may_save = maySave != 0; + if (!data->listener->contextLoadSslClientCertPw(password, QString::FROMUTF8(realm))) + return SVN_NO_ERROR; + + svn_auth_cred_ssl_client_cert_pw_t *cred_ = + (svn_auth_cred_ssl_client_cert_pw_t *) + apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_pw_t)); + + cred_->password = password.TOUTF8(); + cred_->may_save = may_save; + *cred = cred_; + + return SVN_NO_ERROR; +} + +svn_error_t * ContextData::onSslClientCertPwPrompt( + svn_auth_cred_ssl_client_cert_pw_t **cred, + void *baton, + const char *realm, + svn_boolean_t maySave, + apr_pool_t *pool) +{ + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + + QString password; + bool may_save = maySave != 0; + if (!data->listener->contextSslClientCertPwPrompt (password, QString::FROMUTF8(realm), may_save)) + return data->generate_cancel_error(); + + svn_auth_cred_ssl_client_cert_pw_t *cred_ = + (svn_auth_cred_ssl_client_cert_pw_t *) + apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_pw_t)); + + cred_->password = password.TOUTF8(); + cred_->may_save = may_save; + *cred = cred_; + + return SVN_NO_ERROR; +} + +void ContextData::setListener(ContextListener * _listener) +{ + listener = _listener; +} + +ContextListener * ContextData::getListener() const +{ + return listener; +} + +void ContextData::reset() +{ + m_promptCounter = 0; + logIsSet = false; +} + +svn_error_t * ContextData::generate_cancel_error() +{ + return svn_error_create (SVN_ERR_CANCELLED, 0, listener->translate(QString::FROMUTF8("Cancelled by user.")).TOUTF8()); +} + +void ContextData::onProgress(apr_off_t progress, apr_off_t total, void*baton, apr_pool_t*) +{ + ContextData * data = 0; + if (getContextData (baton, &data)!=SVN_NO_ERROR) + { + return; + } + data->getListener()->contextProgress(progress,total); +} + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) +void ContextData::initMimeTypes() +{ + // code take from subversion 1.5 commandline client + const char *mimetypes_file; + svn_error_t * err = 0L; + svn_config_t * cfg = (svn_config_t *)apr_hash_get(m_ctx->config, SVN_CONFIG_CATEGORY_CONFIG, + APR_HASH_KEY_STRING); + + svn_config_get(cfg, &mimetypes_file, + SVN_CONFIG_SECTION_MISCELLANY, + SVN_CONFIG_OPTION_MIMETYPES_FILE, false); + if (mimetypes_file && *mimetypes_file) { + if ((err = svn_io_parse_mimetypes_file(&(m_ctx->mimetypes_map), + mimetypes_file, pool))) { + svn_handle_error2(err, stderr, false, "svn: "); + } + } +} +#endif + +svn_error_t* ContextData::onWcConflictResolver(svn_wc_conflict_result_t**result,const svn_wc_conflict_description_t *description, void *baton, apr_pool_t *pool) +{ +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) + ContextData * data = 0; + SVN_ERR (getContextData (baton, &data)); + ConflictResult cresult; + if (!data->getListener()->contextConflictResolve(cresult,description)) { + return data->generate_cancel_error(); + } + cresult.assignResult(result,pool); + return SVN_NO_ERROR; +#else + Q_UNUSED(result); + Q_UNUSED(description); + Q_UNUSED(baton); + Q_UNUSED(pool); + return svn_error_create (SVN_ERR_CANCELLED, NULL,"invalid subversion version."); +#endif +} + +bool ContextListener::contextConflictResolve(ConflictResult&result,const ConflictDescription&description) +{ + Q_UNUSED(description); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) + result.setChoice(ConflictResult::ChoosePostpone); +#else + Q_UNUSED(result); +#endif + return true; +} + +} diff --git a/src/svnqt/contextdata.hpp b/src/svnqt/contextdata.hpp new file mode 100644 index 0000000..7c03f0a --- /dev/null +++ b/src/svnqt/contextdata.hpp @@ -0,0 +1,338 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNCONTEXTDATA_HPP +#define SVNCONTEXTDATA_HPP + +#include "svnqt/pool.hpp" +#include "svnqt/apr.hpp" +#include "svnqt/commititem.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <svn_client.h> +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) +#include <svn_auth.h> +#endif +#include <qstring.h> + +struct svn_wc_conflict_result_t; +struct svn_wc_conflict_description_t; + +namespace svn { + + class ContextListener; +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ + +class SVNQT_NOEXPORT ContextData{ +public: + ContextData(const QString & configDir_); + ~ContextData(); + + // data methods + svn_client_ctx_t*ctx(); + const QString&configDir()const; + void setListener (ContextListener * listener); + ContextListener * getListener () const; + void reset(); + + // svn methods + void setAuthCache(bool value); + /** @see Context::setLogin */ + void setLogin (const QString& usr, const QString& pwd); + /** @see Context::setLogMessage */ + void setLogMessage (const QString& msg); + const QString&getLogMessage ()const; + /** + * if the @a listener is set, use it to retrieve the log + * message using ContextListener::contextGetLogMessage. + * This return values is given back, then. + * + * if the @a listener is not set the its checked whether + * the log message has been set using @a setLogMessage + * yet. If not, return false otherwise true + * + * @param msg log message + * @retval false cancel + */ + bool retrieveLogMessage (QString & msg,const CommitItemList&); + + /** + * if the @a listener is set call the method + * @a contextNotify + */ + void notify (const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision); + void notify (const svn_wc_notify_t *action); + /** + * if the @a listener is set call the method + * @a contextCancel + */ + bool cancel(); + const QString& getUsername () const; + const QString& getPassword () const; + + /** + * if the @a listener is set and no password has been + * set yet, use it to retrieve login and password using + * ContextListener::contextGetLogin. + * + * if the @a listener is not set, check if setLogin + * has been called yet. + * + * @return continue? + * @retval false cancel + */ + bool + retrieveLogin (const char * username_, + const char * realm, + bool &may_save); + /** + * if the @a listener is set and no password has been + * set yet, use it to retrieve login and password using + * ContextListener::contextGetSavedLogin. + * + * if the @a listener is not set, check if setLogin + * has been called yet. + * + * @return continue? + * @retval false cancel + */ + bool + retrieveSavedLogin(const char * username_, + const char * realm, + bool &may_save); + /** + * if the @a listener is set and no password has been + * set yet, use it to retrieve login and password using + * ContextListener::contextGetCachedLogin. + * + * if the @a listener is not set, check if setLogin + * has been called yet. + * + * @return continue? + * @retval false cancel + */ + bool + retrieveCachedLogin(const char * username_, + const char * realm, + bool &may_save); + +protected: + // static methods + /** + * the @a baton is interpreted as ContextData * + * Several checks are performed on the baton: + * - baton == 0? + * - baton->Data + * - listener set? + * + * @param baton + * @param data returned data if everything is OK + * @retval SVN_NO_ERROR if everything is fine + * @retval SVN_ERR_CANCELLED on invalid values + */ + static svn_error_t * + getContextData (void * baton, ContextData ** data); + + /** + * this function gets called by the subversion api function + * when a log message is needed. This is the case on a commit + * for example + */ + static svn_error_t * + onLogMsg (const char **log_msg, + const char **tmp_file, + apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool); + + /** + * this function gets called by the subversion api function + * when a log message is needed. This is the case on a commit + * for example + */ + static svn_error_t * + onLogMsg2 (const char **log_msg, + const char **tmp_file, + const apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) + /** + * this function gets called by the subversion api function + * when a log message is needed. This is the case on a commit + * for example + */ + static svn_error_t * + onLogMsg3 (const char **log_msg, + const char **tmp_file, + const apr_array_header_t * commit_items, + void *baton, + apr_pool_t * pool); +#endif + + /** + * this is the callback function for the subversion + * api functions to signal the progress of an action + */ + static void + onNotify (void * baton, + const char *path, + svn_wc_notify_action_t action, + svn_node_kind_t kind, + const char *mime_type, + svn_wc_notify_state_t content_state, + svn_wc_notify_state_t prop_state, + svn_revnum_t revision); + /** + * this is the callback function for the subversion 1.2 + * api functions to signal the progress of an action + * + * @todo right now we forward only to @a onNotify, + * but maybe we should a notify2 to the listener + * @since subversion 1.2 + */ + static void + onNotify2(void*baton,const svn_wc_notify_t *action,apr_pool_t */*tpool*/); + /** + * this is the callback function for the subversion + * api functions to signal the progress of an action + * @param baton pointer to a ContextData instance + */ + static svn_error_t * onCancel (void * baton); + + /** + * @see svn_auth_simple_prompt_func_t + * this method is an alternate and called ONEs before onSimplePrompt. + * So we can try load password from other source. + */ + static svn_error_t * + onCachedPrompt(svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool); + + /** + * @see svn_auth_simple_prompt_func_t + * this method is an alternate and called ONEs before onSimplePrompt. + * So we can try load password from other source. + */ + static svn_error_t * + onSavedPrompt(svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool); + /** + * @see svn_auth_simple_prompt_func_t + */ + static svn_error_t * + onSimplePrompt (svn_auth_cred_simple_t **cred, + void *baton, + const char *realm, + const char *username, + svn_boolean_t _may_save, + apr_pool_t *pool); + /** + * @see svn_auth_ssl_server_trust_prompt_func_t + */ + static svn_error_t * + onSslServerTrustPrompt (svn_auth_cred_ssl_server_trust_t **cred, + void *baton, + const char *realm, + apr_uint32_t failures, + const svn_auth_ssl_server_cert_info_t *info, + svn_boolean_t may_save, + apr_pool_t *pool); + static svn_error_t * + onSslClientCertPrompt (svn_auth_cred_ssl_client_cert_t **cred, + void *baton, + apr_pool_t *pool); + /** + * @see svn_auth_ssl_client_cert_pw_prompt_func_t + */ + static svn_error_t * + onFirstSslClientCertPw ( + svn_auth_cred_ssl_client_cert_pw_t **cred, + void *baton, + const char *realm, + svn_boolean_t maySave, + apr_pool_t *pool); + + /** + * @see svn_auth_ssl_client_cert_pw_prompt_func_t + */ + static svn_error_t * + onSslClientCertPwPrompt ( + svn_auth_cred_ssl_client_cert_pw_t **cred, + void *baton, + const char *realm, + svn_boolean_t maySave, + apr_pool_t *pool); + + /** + * @see svn_client_ctx_t::progress_func + */ + static void onProgress(apr_off_t progress, apr_off_t total, void *baton, apr_pool_t *pool); + + /** + * @see svn_wc_conflict_resolver_func_t + * @since subversion 1.5 + */ + static svn_error_t* onWcConflictResolver(svn_wc_conflict_result_t**result,const svn_wc_conflict_description_t *description, void *baton, apr_pool_t *pool); + + // extra methods + svn_error_t * + generate_cancel_error(); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || (SVN_VER_MAJOR > 2)) + /** read in mimetypes map + * @since subversion 1.5 + */ + void initMimeTypes(); +#endif +protected: + Apr apr; + + ContextListener * listener; + bool logIsSet; + int m_promptCounter; + Pool pool; + svn_client_ctx_t*m_ctx; + QString username; + QString password; + QString logMessage; + QString m_ConfigDir; + +}; + +} + +#endif diff --git a/src/svnqt/datetime.cpp b/src/svnqt/datetime.cpp new file mode 100644 index 0000000..496a04b --- /dev/null +++ b/src/svnqt/datetime.cpp @@ -0,0 +1,170 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// apr +#include "apr_date.h" + +// svncpp +#include "datetime.hpp" + + +namespace svn +{ + DateTime::DateTime () + : m_time() + { + } + + DateTime::DateTime (const apr_time_t time) + : m_time() + { + setAprTime(time); + } + + DateTime::DateTime(const QDateTime&dt) + : m_time(dt) + { + } + + DateTime::DateTime (const DateTime & dateTime) + : m_time(dateTime.m_time) + { + } + + const DateTime & + DateTime::operator =(const DateTime & dateTime) + { + m_time = dateTime.m_time; + return *this; + } + + bool DateTime::operator<(const DateTime&dateTime)const + { + return m_time<dateTime.m_time; + } + + bool DateTime::operator>(const DateTime&dateTime)const + { + return dateTime<*this; + } + + bool DateTime::operator!=(const DateTime&dateTime)const + { + return *this<dateTime||dateTime<*this; + } + bool DateTime::operator==(const DateTime&dateTime)const + { + return !(*this!=dateTime); + } + + bool + DateTime::operator ==(const DateTime & dateTime) + { + return m_time == dateTime.m_time; + } + + bool + DateTime::operator !=(const DateTime & dateTime) + { + return m_time != dateTime.m_time; + } + bool + DateTime::operator<=(const DateTime&dateTime)const + { + return *this==dateTime||*this<dateTime; + } + bool + DateTime::operator>=(const DateTime&dateTime)const + { + return *this==dateTime||*this>dateTime; + } + + bool + DateTime::IsValid () const + { + return m_time.isValid(); + } + + apr_time_t + DateTime::GetAPRTimeT () const + { + apr_time_t aTime; + apr_time_ansi_put(&aTime,m_time.toTime_t()); + return aTime; + } + + bool + DateTime::SetRFC822Date (const char* date) + { + apr_time_t aTime = apr_date_parse_rfc(date); + setAprTime(aTime); + return IsValid(); + } + + DateTime::operator const QDateTime&()const + { + return m_time; + } + + const QDateTime&DateTime::toQDateTime()const + { + return *this; + } + + void DateTime::setAprTime(apr_time_t aTime) + { +#if QT_VERSION < 0x040000 + if (aTime<0)m_time.setTime_t(0,Qt::LocalTime); + else m_time.setTime_t(aTime/(1000*1000),Qt::LocalTime); +#else + m_time.setTimeSpec(Qt::LocalTime); + if (aTime<0)m_time.setTime_t(0); + else m_time.setTime_t(aTime/(1000*1000)); +#endif + } + + QString DateTime::toString(const QString&format)const + { + return m_time.toString(format); + } +} + +/*! + \fn svn::DateTime::toTime_t() + */ +unsigned int svn::DateTime::toTime_t()const +{ + return m_time.toTime_t(); +} + +void svn::DateTime::setTime_t(unsigned int sec) +{ + m_time.setTime_t(sec); +} diff --git a/src/svnqt/datetime.hpp b/src/svnqt/datetime.hpp new file mode 100644 index 0000000..06fedb4 --- /dev/null +++ b/src/svnqt/datetime.hpp @@ -0,0 +1,166 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_DATETIME_HPP_ +#define _SVNCPP_DATETIME_HPP_ + +#include "svnqt/svnqt_defines.hpp" + +#include <qdatetime.h> + +// subversion api +#include "svn_types.h" + + +namespace svn +{ + /** + * Class that encapsulates apr_time_t. + * + * @see apr_time_t + */ + class SVNQT_EXPORT DateTime + { + private: + QDateTime m_time; + + public: + + /** + * Default Constructor + */ + DateTime (); + + /** + * Constructor + * + * @param time number of microseconds since 00:00:00 january 1, 1970 UTC + */ + DateTime (const apr_time_t time); + + /** + * Constructor + * + * @param dt QDateTime class + */ + DateTime(const QDateTime&dt); + + /** + * Copy constructor + * + * @param dateTime Source + */ + DateTime (const DateTime & dateTime); + + /** + * @param dateTime Source + */ + const DateTime & + operator =(const DateTime & dateTime); + + /** + * @param dateTime Comparator + */ + bool + operator ==(const DateTime & dateTime); + /** + * @param dateTime Comparator + */ + bool + operator !=(const DateTime & dateTime); + + bool + operator<(const DateTime&dateTime)const; + bool + operator>(const DateTime&dateTime)const; + bool + operator!=(const DateTime&dateTime)const; + bool + operator==(const DateTime&dateTime)const; + bool + operator<=(const DateTime&dateTime)const; + bool + operator>=(const DateTime&dateTime)const; + + + /** + * @return Is a valid (non-zero) date + */ + bool + IsValid () const; + + /** + * @return APR apr_time_t + */ + apr_time_t + GetAPRTimeT () const; + + /** + * @return QDateTime object + */ + operator const QDateTime&()const; + + /** + * @return QDateTime object + */ + const QDateTime&toQDateTime()const; + + /** + * @param format format string + * @return formatted string + * @see QDateTime::toString + */ + QString toString(const QString&format)const; + + /** + * Set from date string of the form below, using apr_date_parse_rfc + * + * <PRE> + * Sun, 06 Nov 1994 08:49:37 GMT + * </PRE> + * + * @see apr_date_parse_rfc + * @return Successfully parsed + */ + bool + SetRFC822Date (const char* date); + + void setAprTime(apr_time_t aTime); + unsigned int toTime_t()const; + void setTime_t(unsigned int sec); + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/diff_data.cpp b/src/svnqt/diff_data.cpp new file mode 100644 index 0000000..a5f66f9 --- /dev/null +++ b/src/svnqt/diff_data.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** + * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "diff_data.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/exception.hpp" + +#include <qfile.h> + +#include <svn_version.h> +#include <svn_io.h> +#include <svn_path.h> + +namespace svn +{ + DiffData::DiffData(const Path&aTmpPath,const Path&_p1,const Revision&_r1,const Path&_p2,const Revision&_r2) + :m_Pool(),m_tmpPath(aTmpPath), + m_outFile(0),m_errFile(0),m_outFileName(0),m_errFileName(0), + m_p1(_p1),m_p2(_p2),m_r1(_r1),m_r2(_r2), + m_working_copy_present(false),m_url_is_present(false) + { + init(); + } + + void DiffData::init() + { + svn_error_t * error; +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + error = svn_io_open_unique_file2(&m_outFile, &m_outFileName, + m_tmpPath.path().TOUTF8(), + ".tmp", + svn_io_file_del_on_pool_cleanup, m_Pool); +#else + error = svn_io_open_unique_file (&m_outFile, &m_outFileName, + m_tmpPath.path().TOUTF8(), + ".tmp", + FALSE, m_Pool); +#endif + if (error!=0) { + clean(); + throw ClientException (error); + } +#if (SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4) + error = svn_io_open_unique_file2(&m_errFile, &m_errFileName, + m_tmpPath.path().TOUTF8(), + ".tmp", + svn_io_file_del_on_pool_cleanup, m_Pool); +#else + error = svn_io_open_unique_file (&m_errFile, &m_errFileName, + m_tmpPath.path().TOUTF8(), + ".tmp", + FALSE, m_Pool); +#endif + if (error!=0) { + clean(); + throw ClientException (error); + } + if (svn_path_is_url(m_p1.cstr())) { + m_url_is_present = true; + } else { + m_working_copy_present = true; + } + if (svn_path_is_url(m_p2.cstr())) { + m_url_is_present = true; + } else { + m_working_copy_present = true; + } + + if (m_r1.revision()->kind==svn_opt_revision_unspecified && m_working_copy_present) { + m_r1 = svn_opt_revision_base; + } + if (m_r2.revision()->kind==svn_opt_revision_unspecified) { + m_r2 = m_working_copy_present?svn_opt_revision_working : svn_opt_revision_head; + } + } + + DiffData::~DiffData() + { + clean(); + } + + void DiffData::clean() + { + close(); +#if !((SVN_VER_MAJOR >= 1) && (SVN_VER_MINOR >= 4)) + if (m_outFileName != 0) { + svn_error_clear (svn_io_remove_file (m_outFileName, m_Pool)); + m_outFileName=0; + } + if (m_errFileName != 0) { + svn_error_clear (svn_io_remove_file (m_errFileName, m_Pool)); + m_errFileName=0; + } +#endif + } + + void DiffData::close() + { + if (m_outFile != 0) { + svn_io_file_close(m_outFile,m_Pool); + m_outFile=0; + } + if (m_errFile != 0) { + svn_io_file_close(m_errFile,m_Pool); + m_errFile=0; + } + } + + QByteArray DiffData::content() + { + if (!m_outFileName) { + return QByteArray(); + } + close(); + QFile fi(m_outFileName); +#if QT_VERSION < 0x040000 + if (!fi.open(IO_ReadOnly|IO_Raw)) { + throw ClientException(QString("%1 '%2'").arg(fi.errorString()).arg(m_outFileName)); +#else + if (!fi.open(QIODevice::ReadOnly)) { + throw ClientException(QString("%1 '%2'").arg(fi.errorString()).arg(m_outFileName).toLatin1().constData()); +#endif + } + + QByteArray res = fi.readAll(); + fi.close(); + return res; + } +} diff --git a/src/svnqt/diff_data.hpp b/src/svnqt/diff_data.hpp new file mode 100644 index 0000000..c92c8ac --- /dev/null +++ b/src/svnqt/diff_data.hpp @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef __DIFF_DATA +#define __DIFF_DATA + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/pool.hpp" +#include "path.hpp" +#include "revision.hpp" + +#include <qglobal.h> + +#if QT_VERSION < 0x040000 + #include <qstring.h> +#else + #include <QtCore> +#endif + +struct apr_file_t; + +namespace svn +{ + class Path; + + class SVNQT_NOEXPORT DiffData + { + protected: + Pool m_Pool; + Path m_tmpPath; + apr_file_t*m_outFile; + apr_file_t*m_errFile; + const char*m_outFileName; + const char*m_errFileName; + + Path m_p1,m_p2; + Revision m_r1,m_r2; + + bool m_working_copy_present,m_url_is_present; + + void init(); + void clean(); + void close(); + + public: + DiffData(const Path&aTmpPath,const Path&,const Revision&,const Path&,const Revision&); + virtual ~DiffData(); + + apr_file_t*outFile(){return m_outFile;} + apr_file_t*errFile(){return m_errFile;} + const Revision& r1()const{return m_r1;} + const Revision& r2()const{return m_r2;} + + QByteArray content(); + }; +} + +#endif diff --git a/src/svnqt/diffoptions.cpp b/src/svnqt/diffoptions.cpp new file mode 100644 index 0000000..7ada9c8 --- /dev/null +++ b/src/svnqt/diffoptions.cpp @@ -0,0 +1,144 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "diffoptions.hpp" +#include "stringarray.hpp" +#include "pool.hpp" + +#include <svn_diff.h> + +namespace svn +{ + struct DiffOptionsData + { + DiffOptions::IgnoreSpace _ignorespace; + bool _ignoreeol; + bool _showc; + + DiffOptionsData() + { + _ignorespace=DiffOptions::IgnoreSpaceNone; + _ignoreeol = _showc = false; + } + }; + + DiffOptions::DiffOptions() + :m_data(new DiffOptionsData()) + { + } + + void DiffOptions::init(const svn_diff_file_options_t*_diffopts) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + m_data->_ignoreeol = _diffopts->ignore_eol_style; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + m_data->_showc = _diffopts->show_c_function; +#else + m_data->_showc = false; +#endif + switch (_diffopts->ignore_space) { + case svn_diff_file_ignore_space_change: + m_data->_ignorespace = IgnoreSpaceChange; + break; + case svn_diff_file_ignore_space_all: + m_data->_ignorespace = IgnoreSpaceAll; + break; + case svn_diff_file_ignore_space_none: + default: + m_data->_ignorespace = IgnoreSpaceNone; + break; + } +#else + Q_UNUSED(_diffopts); +#endif + } + + DiffOptions::DiffOptions(const QStringList&options) + :m_data(new DiffOptionsData()) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + Pool pool; + StringArray _ar(options); + svn_diff_file_options_t * _diffopts = svn_diff_file_options_create(pool); + if (_diffopts) { + svn_error_t*error = svn_diff_file_options_parse(_diffopts,_ar.array(pool),pool); + if (error==0) { + init(_diffopts); + } + } +#else + Q_UNUSED(options) +#endif + } + + DiffOptions::DiffOptions(const svn_diff_file_options_t*options) + :m_data(new DiffOptionsData()) + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + if (options) { + init(options); + } +#else + Q_UNUSED(options) +#endif + } + + svn_diff_file_options_t*DiffOptions::options(const Pool&pool)const + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4)) || (SVN_VER_MAJOR > 1) + svn_diff_file_options_t * _diffopts = svn_diff_file_options_create(pool); + _diffopts->ignore_eol_style = m_data->_ignoreeol; +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + _diffopts->show_c_function = m_data->_showc; +#endif + switch (m_data->_ignorespace) { + case IgnoreSpaceChange: + _diffopts->ignore_space=svn_diff_file_ignore_space_change; + break; + case IgnoreSpaceAll: + _diffopts->ignore_space=svn_diff_file_ignore_space_all; + break; + case IgnoreSpaceNone: + default: + _diffopts->ignore_space=svn_diff_file_ignore_space_none; + break; + } + return _diffopts; +#else + Q_UNUSED(pool); + return 0; +#endif + } + + DiffOptions::DiffOptions(const DiffOptions&old) + :m_data(new DiffOptionsData()) + { + m_data->_showc = old.m_data->_showc; + m_data->_ignorespace=old.m_data->_ignorespace; + m_data->_ignoreeol=old.m_data->_ignoreeol; + } + + DiffOptions::~DiffOptions() + { + delete m_data; + m_data=0; + } +} diff --git a/src/svnqt/diffoptions.hpp b/src/svnqt/diffoptions.hpp new file mode 100644 index 0000000..5509821 --- /dev/null +++ b/src/svnqt/diffoptions.hpp @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _DIFF_OPTIONS_HPP +#define _DIFF_OPTIONS_HPP + +#include "svnqt/svnqt_defines.hpp" + +namespace svn { + class Pool; + struct DiffOptionsData; +} + +struct svn_diff_file_options_t; +class QStringList; + +namespace svn +{ + /** c++ wrapper for svn_diffoptions_t + * + * This is needed until svnqt stops support for subversion prior 1.4 + */ + class SVNQT_EXPORT DiffOptions + { + public: + enum IgnoreSpace { + IgnoreSpaceNone, + IgnoreSpaceChange, + IgnoreSpaceAll + }; + protected: + DiffOptionsData* m_data; + void init(const svn_diff_file_options_t*options); + + public: + DiffOptions(); + /** Initialize options with values depending on options. + * Supported types are: + * - --ignore-space-change, -b + * - --ignore-all-space, -w + * - --ignore-eol-style + * - --unified, -u (for compatibility, does nothing). + * @sa svn_diff_file_options_parse + */ + DiffOptions(const QStringList&options); + + /** Initialize options with values depending on options. + * Only if build against subversion 1.4 or newer. + */ + DiffOptions(const svn_diff_file_options_t*options); + + /** copy operator + */ + DiffOptions(const DiffOptions&old); + + ~DiffOptions(); + + svn_diff_file_options_t*options(const Pool&pool)const; + }; +} + +#endif diff --git a/src/svnqt/dirent.cpp b/src/svnqt/dirent.cpp new file mode 100644 index 0000000..480546f --- /dev/null +++ b/src/svnqt/dirent.cpp @@ -0,0 +1,186 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// svncpp +#include "svnqt/dirent.hpp" +#include "svnqt/lock_entry.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +namespace svn +{ + class SVNQT_NOEXPORT DirEntry_Data + { + public: + QString name; + svn_node_kind_t kind; + QLONG size; + bool hasProps; + svn_revnum_t createdRev; + DateTime time; + QString lastAuthor; + LockEntry m_Lock; + + DirEntry_Data () + : kind (svn_node_unknown), size (0), hasProps(false), + createdRev (0), time (0), m_Lock() + { + } + + DirEntry_Data (const QString& _name, const svn_dirent_t * dirEntry) + : name (_name), kind (dirEntry->kind), size (dirEntry->size), + hasProps (dirEntry->has_props != 0), + createdRev (dirEntry->created_rev), time (dirEntry->time), m_Lock() + { + lastAuthor = dirEntry->last_author == 0 ? QString::fromLatin1("") : QString::FROMUTF8(dirEntry->last_author); + } + + DirEntry_Data (const DirEntry & src) + { + init (src); + } + + void + init (const DirEntry & src) + { + name = src.name (); + kind = src.kind (); + size = src.size (); + hasProps = src.hasProps (); + createdRev = src.createdRev (); + time = src.time (); + lastAuthor = src.lastAuthor (); + m_Lock = src.lockEntry(); + } + }; + + DirEntry::DirEntry () + : m (new DirEntry_Data ()) + { + } + + DirEntry::DirEntry (const QString& name, const svn_dirent_t * dirEntry) + : m (new DirEntry_Data (name, dirEntry)) + { + } + + DirEntry::DirEntry (const QString& name, const svn_dirent_t * dirEntry,const svn_lock_t*lockEntry) + : m (new DirEntry_Data (name, dirEntry)) + { + setLock(lockEntry); + } + + DirEntry::DirEntry (const QString& name, const svn_dirent_t * dirEntry,const LockEntry&lockEntry) + : m (new DirEntry_Data (name, dirEntry)) + { + m->m_Lock = lockEntry; + } + + DirEntry::DirEntry (const DirEntry & src) + : m (new DirEntry_Data (src)) + { + } + + DirEntry::~DirEntry () + { + delete m; + } + + svn_node_kind_t + DirEntry::kind () const + { + return m->kind; + } + + QLONG + DirEntry::size () const + { + return m->size; + } + + bool + DirEntry::hasProps () const + { + return m->hasProps; + } + + svn_revnum_t + DirEntry::createdRev () const + { + return m->createdRev; + } + + const DateTime& + DirEntry::time () const + { + return m->time; + } + + const QString& + DirEntry::lastAuthor () const + { + return m->lastAuthor; + } + + const QString& + DirEntry::name () const + { + return m->name; + } + + const LockEntry& + DirEntry::lockEntry() const + { + return m->m_Lock; + } + + void + DirEntry::setLock(const svn_lock_t*_l) + { + m->m_Lock.init(_l); + } + + DirEntry & + DirEntry::operator= (const DirEntry & dirEntry) + { + if (this == &dirEntry) + return *this; + + m->init (dirEntry); + return *this; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/dirent.hpp b/src/svnqt/dirent.hpp new file mode 100644 index 0000000..9b7c3e2 --- /dev/null +++ b/src/svnqt/dirent.hpp @@ -0,0 +1,131 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_DIRENT_HPP_ +#define _SVNCPP_DIRENT_HPP_ + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/lock_entry.hpp" +#include "svnqt/datetime.hpp" + +// subversion api +#include "svn_client.h" + +#include <qstring.h> + +namespace svn +{ + class DirEntry_Data; + + class SVNQT_EXPORT DirEntry + { + public: + /** + * default constructor + */ + DirEntry (); + + /** + * constructor for existing @a svn_dirent_t entries + */ + DirEntry (const QString& name, const svn_dirent_t * dirEntry); + /** + * constructor for existing @a svn_dirent_t entries + */ + DirEntry (const QString& name, const svn_dirent_t * dirEntry,const svn_lock_t*lockEntry); + + DirEntry (const QString& name, const svn_dirent_t * dirEntry,const LockEntry&lockEntry); + /** + * copy constructor + */ + DirEntry (const DirEntry & src); + + /** + * destructor + */ + ~DirEntry (); + + /** + * assignment operator + */ + DirEntry & + operator = (const DirEntry &); + + const QString& + name () const; + + svn_node_kind_t + kind () const; + + QLONG + size () const; + + bool + hasProps () const; + + svn_revnum_t + createdRev () const; + + const DateTime& + time () const; + + const QString& + lastAuthor () const; + + //! The assigned lock entry + /*! + * returns the assigned lock entry if set + * \return a valid or an empty lock + */ + const LockEntry& + lockEntry() const; + + //! initialize and convert the internal lock entry + /*! + * This method should not needed to call outside the lib, it may just used + * inside svn::Client::ls. + * \param aLock the subversion lock description to convert. + */ + void + setLock(const svn_lock_t*aLock); + + + private: + DirEntry_Data * m; + + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/entry.cpp b/src/svnqt/entry.cpp new file mode 100644 index 0000000..27c14cf --- /dev/null +++ b/src/svnqt/entry.cpp @@ -0,0 +1,394 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// svncpp +#include "entry.hpp" + +namespace svn +{ + class SVNQT_NOEXPORT Entry_private + { + protected: + void init_clean(); + public: + Entry_private(); + Entry_private(const Entry_private&src); + virtual ~Entry_private(); + + bool m_valid; + LockEntry m_Lock; + + QString _name,_url,_repos,_uuid,_copyfrom_url,_conflict_old,_conflict_new,_conflict_wrk,_prejfile,_checksum,_cmt_author; + bool _copied,_deleted,_absent,_incomplete; + svn_revnum_t _revision,_copyfrom_rev,_cmt_rev; + svn_node_kind_t _kind; + svn_wc_schedule_t _schedule; + DateTime _text_time,_prop_time,_cmt_date; + + /** + * initializes the members + */ + void + init (const svn_wc_entry_t * src); + void + init(const Entry_private&src); + void + init(const QString&url,const DirEntryPtr&src); + void + init(const QString&url,const InfoEntry&src); + }; + + void Entry_private::init_clean() + { + _name = _url = _repos = _uuid = _copyfrom_url = _conflict_old = _conflict_new = _conflict_wrk + = _prejfile = _checksum = _cmt_author = QString::null; + _revision = _copyfrom_rev = _cmt_rev = -1; + _kind = svn_node_unknown; + _schedule = svn_wc_schedule_normal; + _text_time = _prop_time = _cmt_date = 0; + _copied = _deleted = _absent = _incomplete = false; + } + + Entry_private::Entry_private() + : m_valid (false),m_Lock() + { + init_clean(); + } + + Entry_private::Entry_private(const Entry_private&src) + : m_valid (false),m_Lock() + { + init_clean(); + init(src); + } + + Entry_private::~Entry_private() + { + } + + void + Entry_private::init (const svn_wc_entry_t * src) + { + if (src) { + // copy & convert the contents of src + _name = QString::FROMUTF8(src->name); + _revision = src->revision; + _url = QString::FROMUTF8(src->url); + _repos = QString::FROMUTF8(src->repos); + _uuid = QString::FROMUTF8(src->uuid); + _kind = src->kind; + _schedule = src->schedule; + _copied = src->copied!=0; + _deleted = src->deleted!=0; + _absent = src->absent!=0; + _incomplete = src->incomplete!=0; + _copyfrom_url=QString::FROMUTF8(src->copyfrom_url); + _copyfrom_rev = src->copyfrom_rev; + _conflict_old = QString::FROMUTF8(src->conflict_old); + _conflict_new = QString::FROMUTF8(src->conflict_new); + _conflict_wrk = QString::FROMUTF8(src->conflict_wrk); + _prejfile = QString::FROMUTF8(src->prejfile); + _text_time = src->text_time; + _prop_time = src->prop_time; + _checksum = QString::FROMUTF8(src->checksum); + _cmt_rev = src->cmt_rev; + _cmt_date = src->cmt_date; + _cmt_author = QString::FROMUTF8(src->cmt_author); + m_Lock.init(src); + m_valid = true; + } else { + m_valid = false; + m_Lock=LockEntry(); + _name= + _url=_repos=_uuid=_copyfrom_url=_conflict_old=_conflict_new=_conflict_wrk=_prejfile=_checksum=_cmt_author= QString::null; + _copied=_deleted=_absent=_incomplete = false; + _kind = svn_node_unknown; + _schedule=svn_wc_schedule_normal; + _text_time=_prop_time=_cmt_date=0; + } + } + void + Entry_private::init(const Entry_private&src) + { + _name=src._name; + _url=src._url; + _repos=src._repos; + _uuid=src._uuid; + _copyfrom_url=src._copyfrom_url; + _conflict_old=src._conflict_old; + _conflict_new=src._conflict_new; + _conflict_wrk=src._conflict_wrk; + _prejfile=src._prejfile; + _checksum=src._checksum; + _cmt_author=src._cmt_author; + _copied=src._copied; + _deleted=src._deleted; + _absent=src._absent; + _incomplete=src._incomplete; + _revision=src._revision; + _copyfrom_rev=src._copyfrom_rev; + _cmt_rev=src._cmt_rev; + _kind=src._kind; + _schedule=src._schedule; + _text_time=src._text_time; + _prop_time=src._prop_time; + _cmt_date=src._cmt_date; + _kind = src._kind; + m_Lock=src.m_Lock; + m_valid=src.m_valid; + } + + void Entry_private::init(const QString&url,const DirEntryPtr&dirEntry) + { + init(0); + _url = url; + if (dirEntry) { + _name=dirEntry->name(); + _revision = dirEntry->createdRev(); + _kind = dirEntry->kind(); + _schedule = svn_wc_schedule_normal; + _text_time = dirEntry->time (); + _prop_time = dirEntry->time (); + _cmt_rev = dirEntry->createdRev (); + _cmt_date = dirEntry->time (); + _cmt_author = dirEntry->lastAuthor (); + m_Lock=dirEntry->lockEntry(); + m_valid = true; + } + } + + void Entry_private::init(const QString&url,const InfoEntry&src) + { + init(0); + _name = src.Name(); + _url = url; + _revision = src.revision(); + _kind = src.kind (); + _schedule = svn_wc_schedule_normal; + _text_time = src.textTime (); + _prop_time = src.propTime (); + _cmt_rev = src.cmtRev (); + _cmt_date = src.cmtDate(); + _cmt_author = src.cmtAuthor(); + m_Lock=src.lockEntry(); + m_valid = true; + } + + Entry::Entry (const svn_wc_entry_t * src) + : m_Data(new Entry_private()) + { + m_Data->init (src); + } + + Entry::Entry (const Entry & src) + : m_Data(new Entry_private()) + { + if (src.m_Data) { + m_Data->init(*(src.m_Data)); + } else { + m_Data->init(0); + } + } + + Entry::Entry (const QString&url,const DirEntryPtr&src) + : m_Data(new Entry_private()) + { + m_Data->init(url,src); + } + + Entry::Entry (const QString&url,const InfoEntry&src) + : m_Data(new Entry_private()) + { + m_Data->init(url,src); + } + + Entry::~Entry () + { + delete m_Data; + } + + Entry & + Entry::operator = (const Entry & src) + { + if (this == &src) + return *this; + if (src.m_Data) { + m_Data->init(*(src.m_Data)); + } else { + m_Data->init(0); + } + return *this; + } + + const LockEntry& + Entry::lockEntry()const + { + return m_Data->m_Lock; + } + + const QString& + Entry::cmtAuthor () const + { + return m_Data->_cmt_author; + } + + const DateTime& + Entry::cmtDate () const + { + return m_Data->_cmt_date; + } + + svn_revnum_t + Entry::cmtRev () const + { + return m_Data->_cmt_rev; + } + const QString& + Entry::checksum () const + { + return m_Data->_checksum; + } + + const DateTime& + Entry::propTime () const + { + return m_Data->_prop_time; + } + + const DateTime& + Entry::textTime () const + { + return m_Data->_text_time; + } + const QString& + Entry::prejfile () const + { + return m_Data->_prejfile; + } + const QString& + Entry::conflictWrk () const + { + return m_Data->_conflict_wrk; + } + + const QString& + Entry::conflictNew () const + { + return m_Data->_conflict_new; + } + const QString& + Entry::conflictOld () const + { + return m_Data->_conflict_old; + } + svn_revnum_t + Entry::copyfromRev () const + { + return m_Data->_copyfrom_rev; + } + const QString& + Entry::copyfromUrl () const + { + return m_Data->_copyfrom_url; + } + + bool + Entry::isAbsent () const + { + return m_Data->_absent; + } + bool + Entry::isDeleted () const + { + return m_Data->_deleted != 0; + } + bool + Entry::isCopied () const + { + return m_Data->_copied != 0; + } + svn_wc_schedule_t + Entry::schedule () const + { + return m_Data->_schedule; + } + svn_node_kind_t + Entry::kind () const + { + return m_Data->_kind; + } + const QString& + Entry::uuid () const + { + return m_Data->_uuid; + } + const QString& + Entry::repos () const + { + return m_Data->_repos; + } + const QString& + Entry::url () const + { + return m_Data->_url; + } + svn_revnum_t + Entry::revision () const + { + return m_Data->_revision; + } + const QString& + Entry::name () const + { + return m_Data->_name; + } + + bool Entry::isValid () const + { + return m_Data->m_valid; + } +} + +/*! + \fn svn::Entry::isDir() + */ +bool svn::Entry::isDir() const +{ + return kind()==svn_node_dir; +} + + +/*! + \fn svn::Entry::isFile() + */ +bool svn::Entry::isFile() const +{ + return kind()==svn_node_file; +} diff --git a/src/svnqt/entry.hpp b/src/svnqt/entry.hpp new file mode 100644 index 0000000..0043622 --- /dev/null +++ b/src/svnqt/entry.hpp @@ -0,0 +1,245 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#ifndef _SVNCPP_ENTRY_HPP_ +#define _SVNCPP_ENTRY_HPP_ + +// svncpp +#include "svnqt/pool.hpp" +#include "svnqt/lock_entry.hpp" +#include "svnqt/dirent.hpp" +#include "svnqt/info_entry.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" + +// subversion api +#include "svn_wc.h" + + +#include <qstring.h> + +namespace svn +{ + class Entry_private; + /** + * C++ API for Subversion. + * This class wraps around @a svn_wc_entry_t. + */ + class SVNQT_EXPORT Entry + { + public: + /** + * default constructor. if @a src is set, + * copy its contents. + * + * If @a src is not set (=0) this will be + * a non-versioned entry. This can be checked + * later with @a isValid (). + * + * @param src another entry to copy from + */ + Entry (const svn_wc_entry_t * src = 0); + + /** + * copy constructor + */ + Entry (const Entry & src); + + /** + * converting constructr + */ + Entry (const QString&url,const DirEntryPtr&src); + /** + * converting constructr + */ + Entry (const QString&url,const InfoEntry&src); + + /** + * destructor + */ + virtual ~Entry (); + + /** + * returns whether this is a valid=versioned + * entry. + * + * @return is entry valid + * @retval true valid entry + * @retval false invalid or unversioned entry + */ + bool isValid () const; + /** + * @return entry's name + */ + const QString& + name () const; + /** + * @return base revision + */ + svn_revnum_t + revision () const; + /** + * @return url in repository + */ + const QString& + url () const; + + /** + * @return canonical repository url + */ + const QString& + repos () const; + /** + * @return repository uuid + */ + const QString& + uuid () const; + /** + * @return node kind (file, dir, ...) + */ + svn_node_kind_t + kind () const; + /** + * @return scheduling (add, delete, replace) + */ + svn_wc_schedule_t + schedule () const; + /** + * @return TRUE if copied + */ + bool + isCopied () const; + /** + * @return true if deleted + */ + bool + isDeleted () const; + /** + * @return true if deleted + */ + bool + isAbsent () const; + /** + * @return copyfrom location + */ + const QString& + copyfromUrl () const; + /** + * @return copyfrom revision + */ + svn_revnum_t + copyfromRev () const; + /** + * @return old version of conflicted file + */ + const QString& + conflictOld () const; + /** + * @return new version of conflicted file + */ + const QString& + conflictNew () const; + /** + * @return working version of conflicted file + */ + const QString& + conflictWrk () const; + /** + * @return property reject file + */ + const QString& + prejfile () const; + /** + * @return last up-to-date time for text contents + * @retval 0 no information available + */ + const DateTime& + textTime () const; + /** + * @return last up-to-date time for properties + * @retval 0 no information available + */ + const DateTime& + propTime()const; + + /** + * @return base64 encoded checksum + * @retval NULL for backwards compatibility + */ + const QString& + checksum () const; + + /** + * @return last revision this was changed + */ + svn_revnum_t + cmtRev () const; + + /** + * @return last date this was changed + */ + const DateTime& + cmtDate () const; + + /** + * @return last commit author of this file + */ + const QString& + cmtAuthor () const; + + /** + * @return lock for that entry + * @since subversion 1.2 + */ + const LockEntry& + lockEntry()const; + + /** + * @return true if entry is marked as dir + */ + bool isDir()const; + /** + * assignment operator + */ + Entry & + operator = (const Entry &); + bool isFile()const; + + private: + Entry_private*m_Data; + }; + +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/exception.cpp b/src/svnqt/exception.cpp new file mode 100644 index 0000000..67bcb60 --- /dev/null +++ b/src/svnqt/exception.cpp @@ -0,0 +1,224 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + + +// svncpp +#include "exception.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +#ifdef HAS_BACKTRACE_H +#include <execinfo.h> +#include <qstringlist.h> +#define SVNQT_BACKTRACE_LENGTH 20 +#endif + +namespace svn +{ + + struct Exception::Data + { + private: + public: + QString message; + apr_status_t apr_err; + + Data (const char * msg) + : message(QString::FROMUTF8(msg)),apr_err(0) + { + } + + Data (const QString& msg) + : message(msg),apr_err(0) + { + } + + + Data (const Data& other) + : message(other.message), apr_err(other.apr_err) + { + } + }; + + Exception::Exception (const char * message) throw () + { + m = new Data (message); + } + + Exception::Exception (const QString& message) throw () + { + m = new Data (message); + } + + Exception::Exception (const Exception & other) throw () + { + m = new Data (*other.m); + } + + Exception::~Exception () throw () + { + delete m; + } + + apr_status_t + Exception::apr_err () const + { + return m->apr_err; + } + + const QString& + Exception::msg () const + { + return m->message; + } + + void Exception::setMessage(const QString&aMsg) + { + m->message=aMsg; + } + + QString Exception::error2msg(svn_error_t*error) + { + QString message = ""; + if (error==0) { + return message; + } + svn_error_t * next = error->child; + if (error->message) + message = QString::FROMUTF8(error->message); + else + { + message = "Unknown error!\n"; + if (error->file) + { + message += QString::FROMUTF8("In file "); + message += QString::FROMUTF8(error->file); + message += QString(" Line %1").arg(error->line); + } + } + while (next != NULL && next->message != NULL) + { + message = message + "\n" + QString::FROMUTF8(next->message); + + next = next->child; + } + + return message; + + } + + ClientException::ClientException (const char*msg) throw () + : Exception (msg) + { + } + + ClientException::ClientException (const QString&msg) throw () + : Exception (msg) + { + } + + ClientException::ClientException (svn_error_t * error) throw () + : Exception ("") + { + init(); + if (error == 0) + return; + + m->apr_err = error->apr_err; + m->message += error2msg(error); + svn_error_clear (error); + } + + ClientException::ClientException (apr_status_t status) throw () + : Exception ("") + { + init(); + m->apr_err = status; + } + + + ClientException::~ClientException () throw () + { + } + + ClientException::ClientException (const ClientException & src) throw () + : Exception (src.msg()) + { + m->apr_err = src.apr_err(); + } + + void ClientException::init() + { +#ifdef USEBACKTRACE + if (m_backTraceConstr.length()==0) { + m_backTraceConstr = getBackTrace(); + m->message=m_backTraceConstr; + } +#else + m_backTraceConstr=""; +#endif + } + + QString ClientException::getBackTrace() + { + QString Result; + qDebug("getBackTrace"); +#ifdef HAS_BACKTRACE_H + qDebug("Generating backtrace"); + void *array[SVNQT_BACKTRACE_LENGTH]; + size_t size; + size_t i; + + size = backtrace (array, SVNQT_BACKTRACE_LENGTH); + if (!size) { + return Result; + } + + char ** strings = backtrace_symbols (array, size); + + QStringList r; + for (i = 0; i < size; ++i) { + r.push_back(QString::number(i) + + QString::FROMUTF8(": ") + + QString::FROMUTF8(strings[i])); + } + Result = QString::FROMUTF8("[\n")+r.join("\n")+QString::FROMUTF8("]\n"); + free (strings); +#endif + return Result; + } + +} +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/exception.hpp b/src/svnqt/exception.hpp new file mode 100644 index 0000000..b83269f --- /dev/null +++ b/src/svnqt/exception.hpp @@ -0,0 +1,138 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_EXCEPTION_H_ +#define _SVNCPP_EXCEPTION_H_ + +#include "svnqt/svnqt_defines.hpp" +// subversion api +#include "svn_client.h" +#include <qstring.h> + +namespace svn +{ + + /** + * Generic exception class. + */ + class SVNQT_EXPORT Exception + { + public: + /** + * Constructor. Assigns the exception reason. + */ + Exception (const char * message) throw (); + Exception (const QString&message) throw(); + + virtual ~Exception () throw (); + + /** + * @return the exception message. + */ + virtual const QString& msg() const; + + /** + * @return the outermost error code. + */ + apr_status_t apr_err () const; + + static QString error2msg(svn_error_t*error); + + protected: + struct Data; + Data * m; + void setMessage(const QString&); + + private: + + Exception (const Exception &) throw (); + + Exception () throw (); + + Exception & operator = (const Exception &); + + }; + + /** + * Subversion client exception class. + */ + class SVNQT_EXPORT ClientException : public Exception + { + public: + /** + * Constructor. Sets the error template and an optional message. + * @param error the error to display. This will get cleared inside with svn_error_clear + * so it isn't usable after that! + */ + ClientException (svn_error_t * error) throw (); + + + /** + * Constructor that takes only an apr errorcode + */ + ClientException (apr_status_t status) throw (); + + /** + * Constructor + */ + ClientException (const char*msg) throw (); + + /** + * Constructor + */ + ClientException (const QString&message) throw(); + + /** + * Copy constructor + */ + ClientException (const ClientException & src) throw (); + + virtual ~ClientException () throw (); + + private: + ClientException () throw (); + + ClientException & operator = (ClientException &); + static QString getBackTrace(); + + void init(); + /// backtrace from constructor; + QString m_backTraceConstr; + + }; + +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/helper.hpp b/src/svnqt/helper.hpp new file mode 100644 index 0000000..fca54d1 --- /dev/null +++ b/src/svnqt/helper.hpp @@ -0,0 +1,98 @@ + +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef __HELPER_HPP +#define __HELPER_HPP + +#include "svnqttypes.hpp" +#include "revision.hpp" +#include <svn_types.h> + +#include <iostream> + +namespace svn +{ + namespace internal + { + class DepthToSvn + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + protected: + svn_depth_t _value; + public: + DepthToSvn(const svn::Depth&val):_value(svn_depth_unknown) + { + switch (val) { + case DepthUnknown: + _value = svn_depth_unknown; + break; + case DepthExclude: + _value = svn_depth_exclude; + break; + case DepthEmpty: + _value = svn_depth_empty; + break; + case DepthFiles: + _value = svn_depth_files; + break; + case DepthImmediates: + _value = svn_depth_immediates; + break; + case DepthInfinity: + default: + _value = svn_depth_infinity; + break; + } + } + + operator svn_depth_t () + { + return _value; + } +#endif + }; + + class RevisionRangesToHash + { +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + protected: + RevisionRanges m_ranges; + public: + RevisionRangesToHash(const RevisionRanges&_input):m_ranges(_input){} + + apr_array_header_t*array(const Pool&pool) + { + apr_array_header_t*ranges=apr_array_make(pool,m_ranges.size(),sizeof(svn_opt_revision_range_t *)); + svn_opt_revision_range_t *range; + + for (unsigned long j=0;j<m_ranges.count();++j) + { + range = (svn_opt_revision_range_t *)apr_palloc(pool, sizeof(*range)); + range->start= *m_ranges[j].first.revision(); + range->end = *m_ranges[j].second.revision(); + APR_ARRAY_PUSH(ranges,svn_opt_revision_range_t *) = range; + } + return ranges; + } +#endif + }; + } +} +#endif diff --git a/src/svnqt/info_entry.cpp b/src/svnqt/info_entry.cpp new file mode 100644 index 0000000..72d714a --- /dev/null +++ b/src/svnqt/info_entry.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnqt/info_entry.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/pool.hpp" +#include <svn_client.h> +#include <svn_path.h> + +namespace svn +{ + + InfoEntry::InfoEntry() + { + init(); + } + + InfoEntry::InfoEntry(const svn_info_t*info,const char*path) + { + init(info,path); + } + + InfoEntry::InfoEntry(const svn_info_t*info,const QString&path) + { + init(info,path); + } + + InfoEntry::~InfoEntry() + { + } + + DateTime InfoEntry::cmtDate()const + { + return m_last_changed_date; + } + DateTime InfoEntry::textTime()const + { + return m_text_time; + } + DateTime InfoEntry::propTime()const + { + return m_prop_time; + } + bool InfoEntry::hasWc()const + { + return m_hasWc; + } + const LockEntry&InfoEntry::lockEntry()const + { + return m_Lock; + } + const QString&InfoEntry::cmtAuthor () const + { + return m_last_author; + } + const QString&InfoEntry::Name()const + { + return m_name; + } + const QString& InfoEntry::checksum()const + { + return m_checksum; + } + const QString& InfoEntry::conflictNew()const + { + return m_conflict_new; + } + const QString& InfoEntry::conflictOld()const + { + return m_conflict_old; + } + const QString& InfoEntry::conflictWrk()const + { + return m_conflict_wrk; + } + const QString& InfoEntry::copyfromUrl()const + { + return m_copyfrom_url; + } + const QString& InfoEntry::prejfile()const + { + return m_prejfile; + } + const QString& InfoEntry::reposRoot()const + { + return m_repos_root; + } + const QString& InfoEntry::url()const + { + return m_url; + } + const QString& InfoEntry::uuid()const + { + return m_UUID; + } + svn_node_kind_t InfoEntry::kind()const + { + return m_kind; + } + const Revision& InfoEntry::cmtRev()const + { + return m_last_changed_rev; + } + const Revision& InfoEntry::copyfromRev()const + { + return m_copy_from_rev; + } + const Revision& InfoEntry::revision()const + { + return m_revision; + } + svn_wc_schedule_t InfoEntry::Schedule()const + { + return m_schedule; + } + const QString&InfoEntry::prettyUrl()const + { + return m_pUrl; + } + bool InfoEntry::isDir()const + { + return kind()==svn_node_dir; + } + const QByteArray&InfoEntry::changeList()const + { + return m_changeList; + } + QLONG InfoEntry::size()const + { + return m_size; + } + QLONG InfoEntry::working_size()const + { + return m_working_size; + } + svn::Depth InfoEntry::depth()const + { + return m_depth; + } +} + +/*! + \fn svn::InfoEntry::init() + */ +void svn::InfoEntry::init() +{ + m_name = ""; + m_last_changed_date=0; + m_text_time = 0; + m_prop_time = 0; + m_hasWc = false; + m_Lock = LockEntry(); + m_checksum = ""; + m_conflict_new = ""; + m_conflict_old = ""; + m_conflict_wrk = ""; + m_copyfrom_url = ""; + m_last_author = ""; + m_prejfile = ""; + m_repos_root = ""; + m_url = ""; + m_pUrl = ""; + m_UUID = ""; + m_kind = svn_node_none; + m_copy_from_rev = SVN_INVALID_REVNUM; + m_last_changed_rev = SVN_INVALID_REVNUM; + m_revision = SVN_INVALID_REVNUM; + m_schedule = svn_wc_schedule_normal; + + m_size = m_working_size = SVNQT_SIZE_UNKNOWN; + m_changeList=QByteArray(); + m_depth = DepthUnknown; +} + +void svn::InfoEntry::init(const svn_info_t*item,const char*path) +{ + init(item,QString::FROMUTF8(path)); +} + +/*! + \fn svn::InfoEntry::init(const svn_info_t*) + */ +void svn::InfoEntry::init(const svn_info_t*item,const QString&path) +{ + if (!item) { + init(); + return; + } + m_name = path; + m_last_changed_date=item->last_changed_date; + m_text_time = item->text_time; + m_prop_time = item->prop_time; + if (item->lock) { + m_Lock.init(item->lock); + } else { + m_Lock = LockEntry(); + } + m_checksum = QString::FROMUTF8(item->checksum); + m_conflict_new = QString::FROMUTF8(item->conflict_new); + m_conflict_old = QString::FROMUTF8(item->conflict_old); + m_conflict_wrk = QString::FROMUTF8(item->conflict_wrk); + m_copyfrom_url = QString::FROMUTF8(item->copyfrom_url); + m_last_author = QString::FROMUTF8(item->last_changed_author); + m_prejfile = QString::FROMUTF8(item->prejfile); + m_repos_root = QString::FROMUTF8(item->repos_root_URL); + m_url = QString::FROMUTF8(item->URL); + m_pUrl = prettyUrl(item->URL); + m_UUID = QString::FROMUTF8(item->repos_UUID); + m_kind = item->kind; + m_copy_from_rev = item->copyfrom_rev; + m_last_changed_rev = item->last_changed_rev; + m_revision = item->rev; + m_hasWc = item->has_wc_info; + m_schedule = item->schedule; + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + m_size = item->size!=SVN_INFO_SIZE_UNKNOWN?QLONG(item->size):SVNQT_SIZE_UNKNOWN; + m_working_size = item->working_size!=SVN_INFO_SIZE_UNKNOWN?QLONG(item->working_size):SVNQT_SIZE_UNKNOWN; + if (item->changelist) { +#if QT_VERSION < 0x040000 + m_changeList = QByteArray(QCString(item->changelist,strlen(item->changelist))); +#else + m_changeList = QByteArray(item->changelist,strlen(item->changelist)); +#endif + } else { + m_changeList=QByteArray(); + } + + switch (item->depth) { + case svn_depth_exclude: + m_depth=DepthExclude; + break; + case svn_depth_empty: + m_depth=DepthEmpty; + break; + case svn_depth_files: + m_depth=DepthFiles; + break; + case svn_depth_immediates: + m_depth=DepthImmediates; + break; + case svn_depth_infinity: + m_depth=DepthInfinity; + break; + case svn_depth_unknown: + default: + m_depth=DepthUnknown; + break; + } +#else + m_size = SVNQT_SIZE_UNKNOWN; + m_working_size = SVNQT_SIZE_UNKNOWN; + m_changeList=QByteArray(); + m_depth = DepthUnknown; +#endif +} + +QString svn::InfoEntry::prettyUrl(const char*_url)const +{ + if (_url) { + Pool pool; + _url = svn_path_uri_decode(_url,pool); + return QString::FROMUTF8(_url); + } + return QString::FROMUTF8(""); +} + +svn::InfoEntry::InfoEntry(const InfoEntry&other) +{ + m_name = other.m_name; + m_last_changed_date=other.m_last_changed_date; + m_text_time = other.m_text_time; + m_prop_time = other.m_prop_time; + m_Lock = other.m_Lock; + m_checksum = other.m_checksum; + m_conflict_new = other.m_conflict_new; + m_conflict_old = other.m_conflict_old; + m_conflict_wrk = other.m_conflict_wrk; + m_copyfrom_url = other.m_copyfrom_url; + m_last_author = other.m_last_author; + m_prejfile = other.m_prejfile; + m_repos_root = other.m_repos_root; + m_url = other.m_url; + m_pUrl = other.m_pUrl; + m_UUID = other.m_UUID; + m_kind = other.m_kind; + m_copy_from_rev = other.m_copy_from_rev; + m_last_changed_rev = other.m_last_changed_rev; + m_revision = other.m_revision; + m_hasWc = other.m_hasWc; + m_schedule = other.m_schedule; + m_size = other.m_size; + m_working_size = other.m_working_size; + +} diff --git a/src/svnqt/info_entry.hpp b/src/svnqt/info_entry.hpp new file mode 100644 index 0000000..91de95c --- /dev/null +++ b/src/svnqt/info_entry.hpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef __INFO_ENTRY_H +#define __INFO_ENTRY_H + +#include <svnqt/lock_entry.hpp> +#include <svnqt/datetime.hpp> +#include <svnqt/revision.hpp> +#include <svnqt/svnqttypes.hpp> + +#include <qstring.h> + +struct svn_info_t; + +namespace svn { + class SVNQT_EXPORT InfoEntry + { +public: + InfoEntry(); + InfoEntry(const svn_info_t*,const char*path); + InfoEntry(const svn_info_t*,const QString&path); + InfoEntry(const InfoEntry&); + ~InfoEntry(); + + void init(const svn_info_t*,const char*path); + void init(const svn_info_t*,const QString&path); + + DateTime cmtDate()const; + DateTime textTime()const; + DateTime propTime()const; + bool hasWc()const; + /** + * @return lock for that entry + * @since subversion 1.2 + */ + const LockEntry&lockEntry()const; + /** + * @return last commit author of this file + */ + const QString&cmtAuthor () const; + const QString&Name()const; + + const QString& checksum()const; + const QString& conflictNew()const; + const QString& conflictOld()const; + const QString& conflictWrk()const; + const QString& copyfromUrl()const; + const QString& prejfile()const; + const QString& reposRoot()const; + const QString& url()const; + const QString& uuid()const; + svn_node_kind_t kind()const; + const Revision& cmtRev()const; + const Revision& copyfromRev()const; + const Revision& revision()const; + svn_wc_schedule_t Schedule()const; + + QLONG size()const; + QLONG working_size()const; + const QByteArray&changeList()const; + svn::Depth depth()const; + + const QString&prettyUrl()const; + + bool isDir()const; + QString prettyUrl(const char*)const; + +protected: + DateTime m_last_changed_date; + DateTime m_text_time; + DateTime m_prop_time; + bool m_hasWc; + LockEntry m_Lock; + QString m_name; + QString m_checksum; + QString m_conflict_new; + QString m_conflict_old; + QString m_conflict_wrk; + QString m_copyfrom_url; + QString m_last_author; + QString m_prejfile; + QString m_repos_root; + QString m_url; + QString m_pUrl; + QString m_UUID; + svn_node_kind_t m_kind; + Revision m_copy_from_rev; + Revision m_last_changed_rev; + Revision m_revision; + svn_wc_schedule_t m_schedule; + + QLONG m_size; + QLONG m_working_size; + QByteArray m_changeList; + svn::Depth m_depth; + +protected: + void init(); + }; +} +#endif diff --git a/src/svnqt/lock_entry.cpp b/src/svnqt/lock_entry.cpp new file mode 100644 index 0000000..cf7ffe1 --- /dev/null +++ b/src/svnqt/lock_entry.cpp @@ -0,0 +1,141 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// svncpp +#include "lock_entry.hpp" +#include "pool.hpp" + +// subversion api +#include "svn_time.h" +#include "svn_version.h" + + +namespace svn +{ + LockEntry::LockEntry () + : date(0),exp(0),owner(""),comment(""),token(""),locked(false) + { + } + + LockEntry::LockEntry ( + const apr_time_t lock_time, + const apr_time_t expiration_time, + const char * lock_owner, + const char * lock_comment, + const char * lock_token) + : date(lock_time),exp(expiration_time), + owner(lock_owner?QString::FROMUTF8(lock_owner):""), + comment(lock_comment?QString::FROMUTF8(lock_comment):""), + token(lock_token?QString::FROMUTF8(lock_token):""), + locked(lock_token?true:false) + { + } + const QString&LockEntry::Comment()const + { + return comment; + } + const QString&LockEntry::Owner()const + { + return owner; + } + const QString&LockEntry::Token()const + { + return token; + } + const DateTime&LockEntry::Date()const + { + return date; + } + const DateTime&LockEntry::Expiration()const + { + return exp; + } + bool LockEntry::Locked()const + { + return locked; + } + void LockEntry::init(const svn_wc_entry_t * src) + { + if (src) { + date = src->lock_creation_date; + locked = src->lock_token?true:false; + token = (src->lock_token?QString::FROMUTF8(src->lock_token):""); + comment = (src->lock_comment?QString::FROMUTF8(src->lock_comment):""); + owner = (src->lock_owner?QString::FROMUTF8(src->lock_owner):""); + } else { + date = 0; + owner = ""; + comment = ""; + token = ""; + locked = false; + } + exp = 0; + } + + void LockEntry::init(const svn_lock_t* src) + { + if (src) { + date = src->creation_date; + locked = src->token?true:false; + token = (src->token?QString::FROMUTF8(src->token):""); + comment = (src->comment?QString::FROMUTF8(src->comment):""); + owner = (src->owner?QString::FROMUTF8(src->owner):""); + } else { + date = 0; + exp = 0; + owner = ""; + comment = ""; + token = ""; + locked = false; + } + + } + + void LockEntry::init( + const apr_time_t lock_time, + const apr_time_t expiration_time, + const char * lock_owner, + const char * lock_comment, + const char * lock_token) + { + date = lock_time; + exp = expiration_time; + locked = lock_token?true:false; + token = lock_token?QString::FROMUTF8(lock_token):""; + owner = lock_owner?QString::FROMUTF8(lock_owner):""; + comment = lock_comment?QString::FROMUTF8(lock_comment):""; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/lock_entry.hpp b/src/svnqt/lock_entry.hpp new file mode 100644 index 0000000..eec3d1f --- /dev/null +++ b/src/svnqt/lock_entry.hpp @@ -0,0 +1,90 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_LOCK_ENTRY_H_ +#define _SVNCPP_LOCK_ENTRY_H_ + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/datetime.hpp" + +#include <qstring.h> + +// apr +#include "apr_time.h" + +// subversion api +#include "svn_types.h" +#include "svn_wc.h" + +namespace svn +{ + class SVNQT_EXPORT LockEntry + { + public: + LockEntry (); + + LockEntry (const apr_time_t lock_time, + const apr_time_t expiration_time, + const char * lock_owner, + const char * lock_comment, + const char * lock_token); + + void init(const svn_wc_entry_t * src); + + void init(const apr_time_t lock_time, + const apr_time_t expiration_time, + const char * lock_owner, + const char * lock_comment, + const char * lock_token); + void init(const svn_lock_t*); + const QString&Comment()const; + const QString&Owner()const; + const QString&Token()const; + const DateTime&Date()const; + const DateTime&Expiration()const; + bool Locked()const; + + protected: + DateTime date; + DateTime exp; + QString owner; + QString comment; + QString token; + bool locked; + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ + diff --git a/src/svnqt/log_entry.cpp b/src/svnqt/log_entry.cpp new file mode 100644 index 0000000..fdd28e8 --- /dev/null +++ b/src/svnqt/log_entry.cpp @@ -0,0 +1,190 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +// svncpp +#include "log_entry.hpp" +#include "pool.hpp" + +// subversion api +#include "svn_time.h" +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) +#include "svn_compat.h" +#endif + + +namespace svn +{ + LogChangePathEntry::LogChangePathEntry ( + const char *path_, + char action_, + const char *copyFromPath_, + const svn_revnum_t copyFromRevision_) + : path(QString::FROMUTF8(path_)), action(action_), + copyFromPath (QString::FROMUTF8(copyFromPath_)), + copyFromRevision (copyFromRevision_) + { + } + + LogChangePathEntry::LogChangePathEntry (const QString &path_, + char action_, + const QString ©FromPath_, + const svn_revnum_t copyFromRevision_) + : path(path_), + action(action_), + copyFromPath(copyFromPath_), + copyToPath(QString::null), + copyFromRevision(copyFromRevision_), + copyToRevision(-1) + { + } + + LogChangePathEntry::LogChangePathEntry() + : path(QString::null),action(0),copyFromPath(QString::null),copyToPath(QString::null), + copyFromRevision(-1),copyToRevision(-1) + { + } + + LogChangePathEntry::LogChangePathEntry (const QString &path_, + char action_, + const QString ©FromPath_, + const svn_revnum_t copyFromRevision_, + const QString ©ToPath_, + const svn_revnum_t copyToRevision_) + : path(path_),action(action_),copyFromPath(copyFromPath_),copyToPath(copyToPath_), + copyFromRevision(copyFromRevision_),copyToRevision(copyToRevision_) + { + } + + LogEntry::LogEntry () + : revision(-1),date(0),author(""),message("") + { + } + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + LogEntry::LogEntry(svn_log_entry_t*log_entry) + : revision(-1),date(0),author(""),message("") + { + Pool pool; + const char *author_; + const char *date_; + const char *message_; + svn_compat_log_revprops_out(&author_, &date_, &message_, log_entry->revprops); + + author = author_ == 0 ? QString::fromLatin1("") : QString::FROMUTF8(author_); + message = message_ == 0 ? QString::fromLatin1("") : QString::FROMUTF8(message_); + setDate(date_); + revision = log_entry->revision; + if (log_entry->changed_paths) { + for (apr_hash_index_t *hi = apr_hash_first (pool, log_entry->changed_paths); + hi != NULL; + hi = apr_hash_next (hi)) + { + const void *pv; + void *val; + apr_hash_this (hi, &pv, NULL, &val); + svn_log_changed_path_t *log_item = reinterpret_cast<svn_log_changed_path_t *> (val); + const char* path = reinterpret_cast<const char*>(pv); + changedPaths.push_back (LogChangePathEntry (path,log_item->action,log_item->copyfrom_path,log_item->copyfrom_rev) ); + } + } + } +#endif + + LogEntry::LogEntry ( + const svn_revnum_t revision_, + const char * author_, + const char * date_, + const char * message_) + { + setDate(date_); + + revision = revision_; + author = author_ == 0 ? QString::fromLatin1("") : QString::FROMUTF8(author_); + message = message_ == 0 ? QString::fromLatin1("") : QString::FROMUTF8(message_); + } + + void LogEntry::setDate(const char*date_) + { + apr_time_t date__ = 0; + if (date_ != 0) + { + Pool pool; + + if (svn_time_from_cstring (&date__, date_, pool) != 0) + date__ = 0; + } + date = date__; + } +} + + +SVNQT_EXPORT QDataStream& operator<<(QDataStream&s,const svn::LogEntry&r) +{ + s << r.revision + << r.author + << r.message + << r.changedPaths + << r.date; + return s; +} + +SVNQT_EXPORT QDataStream& operator<<(QDataStream&s,const svn::LogChangePathEntry&r) +{ + short ac = r.action; + s << r.path + << ac + << r.copyFromPath + << r.copyFromRevision + << r.copyToPath + << r.copyToRevision; + return s; +} + +SVNQT_EXPORT QDataStream& operator>>(QDataStream&s,svn::LogEntry&r) +{ + s >> r.revision + >> r.author + >> r.message + >> r.changedPaths + >> r.date; + return s; +} + +SVNQT_EXPORT QDataStream& operator>>(QDataStream&s,svn::LogChangePathEntry&r) +{ + short ac; + s >> r.path + >> ac + >> r.copyFromPath + >> r.copyFromRevision + >> r.copyToPath + >> r.copyToRevision; + r.action = ac; + return s; +} diff --git a/src/svnqt/log_entry.hpp b/src/svnqt/log_entry.hpp new file mode 100644 index 0000000..cc33f60 --- /dev/null +++ b/src/svnqt/log_entry.hpp @@ -0,0 +1,137 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_LOG_ENTRY_H_ +#define _SVNCPP_LOG_ENTRY_H_ + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/datetime.hpp" + +//Qt +#include <qglobal.h> + +#if QT_VERSION < 0x040000 + +#include <qglobal.h> +#include <qstring.h> +#include <qvaluelist.h> +#include <qmap.h> + +#else + +#include <QtCore> + +#endif + +// apr +#include "apr_time.h" + +// subversion api +#include "svn_types.h" +#include "svn_version.h" + +namespace svn +{ + + class SVNQT_EXPORT LogChangePathEntry + { + public: + LogChangePathEntry (const char *path_, + char action_, + const char *copyFromPath_, + const svn_revnum_t copyFromRevision_); + + LogChangePathEntry (const QString &path_, + char action_, + const QString ©FromPath_, + const svn_revnum_t copyFromRevision_); + + LogChangePathEntry (const QString &path_, + char action_, + const QString ©FromPath_, + const svn_revnum_t copyFromRevision_, + const QString ©ToPath_, + const svn_revnum_t copyToRevision_); + + LogChangePathEntry(); + + QString path; + char action; + QString copyFromPath; + //! future use or useful in backends + QString copyToPath; + + QLONG copyFromRevision; + //! future use or useful in backends + QLONG copyToRevision; + }; + +#if QT_VERSION < 0x040000 + typedef QValueList<LogChangePathEntry> LogChangePathEntries; +#else + typedef QList<LogChangePathEntry> LogChangePathEntries; +#endif + + class SVNQT_EXPORT LogEntry + { + public: + LogEntry (); + + LogEntry (const svn_revnum_t revision, + const char * author, + const char * date, + const char * message); +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5)) || (SVN_VER_MAJOR > 1) + LogEntry(svn_log_entry_t*); +#endif + void setDate(const char*date); + + //! if -1 the entry is a fake entry and not real usable! + QLONG revision; + QLONG date; + QString author; + QString message; + LogChangePathEntries changedPaths; + QLIST<QLONG> m_MergedInRevisions; + }; +} + +SVNQT_EXPORT QDataStream &operator<<(QDataStream&s,const svn::LogEntry&r); +SVNQT_EXPORT QDataStream &operator<<(QDataStream&s,const svn::LogChangePathEntry&r); + +SVNQT_EXPORT QDataStream &operator>>(QDataStream&s,svn::LogEntry&r); +SVNQT_EXPORT QDataStream &operator>>(QDataStream&s,svn::LogChangePathEntry&r); + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/path.cpp b/src/svnqt/path.cpp new file mode 100644 index 0000000..676c151 --- /dev/null +++ b/src/svnqt/path.cpp @@ -0,0 +1,290 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + + +// subversion api +#include "svn_path.h" + +// apr api +#include "apr_file_io.h" + +// svncpp +#include "svnqt/path.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/url.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/exception.hpp" + +#include <qurl.h> + +namespace svn +{ + Path::Path (const char * path) + { + init(QString::FROMUTF8(path)); + } + + Path::Path (const QString & path) + { + init (path); + } + + Path::Path (const Path & path) + : m_path(path.m_path) + { + } + + void + Path::init (const QString& path) + { + Pool pool; + + if (path.isEmpty()) { + m_path = ""; + } else { + const char * int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () ); + if (Url::isValid(path) ) { + if (!svn_path_is_uri_safe(int_path)) { + int_path = svn_path_uri_encode(int_path,pool); + } + } + m_path = QString::FROMUTF8(int_path); +#if QT_VERSION < 0x040000 + if (Url::isValid(path) && m_path.find("@")!=-1 ) { +#else + if (Url::isValid(path) && m_path.indexOf("@")!=-1 ) { +#endif + /// @todo make sure that "@" is never used as revision paramter + QUrl uri = m_path; + m_path = uri.path(); + m_path.replace("@","%40"); +#if QT_VERSION < 0x040000 + m_path = uri.protocol()+"://"+(uri.hasUser()?uri.user()+(uri.hasPassword()?":"+uri.password():"")+"@":"") + +uri.host()+m_path; +#else + m_path = uri.scheme()+"://"+uri.authority()+m_path; +#endif + if (m_path.endsWith("/")) { + int_path = svn_path_internal_style (path.TOUTF8(), pool.pool () ); + m_path = QString::FROMUTF8(int_path); + } + } + } + } + + bool Path::isUrl()const + { + return Url::isValid(m_path); + } + + const QString & + Path::path () const + { + return m_path; + } + + Path::operator const QString&()const + { + return m_path; + } + + QString Path::prettyPath()const + { + if (!Url::isValid(m_path)) { + return m_path; + } + Pool pool; + const char * int_path = svn_path_uri_decode(m_path.TOUTF8(), pool.pool () ); + QString _p = QString::FROMUTF8(int_path); + _p.replace("%40","@"); + return _p; + } + + const QByteArray + Path::cstr() const + { + return m_path.TOUTF8(); + } + + Path& + Path::operator=(const Path & path) + { + if (this == &path) + return *this; + m_path = path.path(); + return *this; + } + + bool + Path::isset () const + { + return m_path.length () > 0; + } + + void + Path::addComponent (const QString& component) + { + Pool pool; + + if (Url::isValid (m_path)) + { + const char * newPath = + svn_path_url_add_component (m_path.TOUTF8(), component.TOUTF8(), pool); + m_path = QString::FROMUTF8(newPath); + } + else + { + svn_stringbuf_t * pathStringbuf = + svn_stringbuf_create (m_path.TOUTF8(), pool); + + svn_path_add_component (pathStringbuf, + component.TOUTF8()); + + m_path = QString::FROMUTF8(pathStringbuf->data); + } + } + + + void + Path::addComponent (const char* component) + { + addComponent (QString::FROMUTF8(component)); + } + + + void + Path::removeLast() + { + Pool pool; + if (m_path.length()<=1) { + m_path=QString::FROMUTF8(""); + } + svn_stringbuf_t*pathStringbuf= + svn_stringbuf_create (m_path.TOUTF8(), pool); + svn_path_remove_component(pathStringbuf); + m_path = QString::FROMUTF8(pathStringbuf->data); + } + + void + Path::split (QString & dirpath, QString & basename) const + { + Pool pool; + + const char * cdirpath; + const char * cbasename; + + svn_path_split (prettyPath().TOUTF8(), &cdirpath, &cbasename, pool); + dirpath = QString::FROMUTF8(cdirpath); + basename = QString::FROMUTF8(cbasename); + } + + + void + Path::split (QString & dir, QString & filename, QString & ext) const + { + QString basename; + + // first split path into dir and filename+ext + split (dir, basename); + + // next search for last . +#if QT_VERSION < 0x040000 + int pos = basename.findRev(QChar('.')); +#else + int pos = basename.lastIndexOf(QChar('.')); +#endif + + if (pos == -1) + { + filename = basename; + ext = QString::fromLatin1(""); + } + else + { + filename = basename.left(pos); + ext = basename.mid(pos+1); + } + } + + Path + Path::getTempDir () + { + const char * tempdir = 0; + Pool pool; + + if (apr_temp_dir_get (&tempdir, pool) != APR_SUCCESS) + { + tempdir = 0; + } + + return tempdir; + } + + void + Path::parsePeg(const QString&pathorurl,Path&_path,svn::Revision&_peg) + { + const char *truepath = 0; + svn_opt_revision_t pegr; + svn_error_t *error = 0; + QByteArray _buf = pathorurl.TOUTF8(); + + Pool pool; + error = svn_opt_parse_path(&pegr, &truepath,_buf,pool); + if (error != 0) { + throw ClientException (error); + } + qDebug("Path: %s",truepath); + _peg = svn::Revision(&pegr); + _path=Path(truepath); + } + + unsigned int + Path::length () const + { + return m_path.length (); + } + + + QString + Path::native () const + { + Pool pool; + + return QString::FROMUTF8(svn_path_local_style (m_path.TOUTF8(), pool)); + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/path.hpp b/src/svnqt/path.hpp new file mode 100644 index 0000000..0d92fc2 --- /dev/null +++ b/src/svnqt/path.hpp @@ -0,0 +1,200 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_PATH_HPP_ +#define _SVNCPP_PATH_HPP_ + +#include <qstring.h> +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" + +namespace svn +{ + /** + * Encapsulation for Subversion Path handling + */ + class SVNQT_EXPORT Path + { + private: + QString m_path; + + /** + * initialize the class + * + * @param path Path string - when url this should NOT hold revision as @ parameter!!!!! (will filtered out) + */ + void init (const QString& path); + + public: + /** + * Constructor that takes a string as parameter. + * The string is converted to subversion internal + * representation. The string is copied. + * + * @param path Path string - when url this should NOT hold revision as @ parameter!!!!! (will filtered out) + */ + Path (const QString & path = QString::null); + + /** + * Constructor + * + * @see Path::Path (const QString &) + * @param path Path string - when url this should NOT hold revision as @ parameter!!!!! (will filtered out) + */ + Path (const char * path); + + /** + * Copy constructor + * + * @param path Path to be copied + */ + Path (const Path & path); + + /** + * Assignment operator + */ + Path& operator=(const Path&); + + /** + * @return Path string + */ + const QString & + path () const; + + /** + * @return Path string + */ + operator const QString&()const; + + /** + * @return Path as pretty url + */ + QString prettyPath()const; + + /** + * @return Path string as c string + */ + const QByteArray cstr() const; + + /** + * check whether a path is set. Right now + * this checks only if the string is non- + * empty. + * + * @return true if there is a path set + */ + bool + isset() const; + + + /** + * adds a new URL component to the path + * + * @param component new component to add + */ + void + addComponent (const char * component); + + + /** + * adds a new URL component to the path + * + * @param component new component to add + */ + void + addComponent (const QString & component); + + /** Reduce path to its parent folder. + * If the path length is 1 (eg., only "/") it will cleared so + * path length will get zero. + * @sa svn_path_remove_component + */ + void + removeLast(); + + + /** + * split path in its components + * + * @param dirpath directory/path component + * @param basename filename + */ + void + split (QString & dirpath, QString & basename) const; + + + /** + * split path in its components including + * file extension + * + * @param dir directory component + * @param filename filename + * @param ext extension (including leading dot ".") + */ + void + split (QString & dir, QString & filename, QString & ext) const; + + + /** + * returns the temporary directory + */ + static Path + getTempDir (); + + /** Parse a string for a peg revision + * @param pathorurl url to parse + * @param _path target to store the cleaned url + * @param _peg target where to store the peg url. + * @throw svn::ClientException on errors + */ + static void + parsePeg(const QString&pathorurl,Path&_path,svn::Revision&_peg); + + + /** return the length of the path-string */ + unsigned int + length () const; + + + /** returns the path with native separators */ + QString + native () const; + + /** returns if the path is a valid url, eg. points to a remote */ + bool isUrl()const; + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/pool.cpp b/src/svnqt/pool.cpp new file mode 100644 index 0000000..34ef947 --- /dev/null +++ b/src/svnqt/pool.cpp @@ -0,0 +1,94 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// svncpp +#include "pool.hpp" + + +namespace svn +{ + bool Pool::s_initialized = false; + + apr_pool_t * + Pool::pool_create (apr_pool_t * parent) + { + if (!s_initialized) { + apr_pool_initialize(); + s_initialized=true; + } + return svn_pool_create (parent); + } + + Pool::Pool (apr_pool_t * parent) + : m_parent (parent), m_pool (pool_create (parent)) + { + } + + Pool::~Pool () + { + if(m_pool) + { + svn_pool_destroy (m_pool); + } + } + + apr_pool_t * + Pool::pool () const + { + return m_pool; + } + + void + Pool::renew () + { + if (m_pool) + { + svn_pool_destroy (m_pool); + } + m_pool = pool_create (m_parent); + } + +//TODO +// apr_pool_t * +// Pool::operator=(const Pool & pool) +// { +// return +// if (this == &path) +// return *this; +// m_path = path.c_str(); +// return *this; +// } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/pool.hpp b/src/svnqt/pool.hpp new file mode 100644 index 0000000..accdd75 --- /dev/null +++ b/src/svnqt/pool.hpp @@ -0,0 +1,92 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_POOL_H_ +#define _SVNCPP_POOL_H_ + +// subversion api +#include "svn_pools.h" + + +namespace svn +{ + /** + * Class for encapsulation of apr/subversion pools + */ + class Pool + { + public: + /** + * creates a subpool new pool to an existing pool + * + * @param parent NULL -> global pool + */ + Pool (apr_pool_t * parent = (apr_pool_t *)0); + + virtual ~ Pool (); + + /** + * @return apr handle to the pool + */ + apr_pool_t * + pool () const; + + /** + * operator to return apr handle to the pool + */ + operator apr_pool_t * () const + { + return m_pool; + } + + /** + * release pool and create a new one + */ + void renew (); + private: + apr_pool_t * m_parent; + apr_pool_t * m_pool; + + Pool& operator=(const Pool&); + + Pool (const Pool &); + + static bool s_initialized; + static apr_pool_t * pool_create (apr_pool_t * parent); + }; +} + +#endif + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/repository.cpp b/src/svnqt/repository.cpp new file mode 100644 index 0000000..2a3dd0e --- /dev/null +++ b/src/svnqt/repository.cpp @@ -0,0 +1,104 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "repository.hpp" +#include "repositorydata.hpp" + +namespace svn { + +namespace repository { + +Repository::Repository(svn::repository::RepositoryListener*aListener) +{ + m_Data=new RepositoryData(aListener); +} + + +Repository::~Repository() +{ + delete m_Data; +} + + +/*! + \fn svn::Repository::Open(const QString&) + */ +void Repository::Open(const QString&name) throw (ClientException) +{ + svn_error_t * error = m_Data->Open(name); + if (error!=0) { + throw ClientException (error); + } +} + +void Repository::CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync, bool _bdbautologremove, bool _pre_1_4_compat, bool _pre_1_5_compat) throw (ClientException) +{ + svn_error_t * error = m_Data->CreateOpen(path,fstype,_bdbnosync,_bdbautologremove,_pre_1_4_compat,_pre_1_5_compat); + if (error!=0) { + throw ClientException (error); + } +} + + +/*! + \fn svn::Repository::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas)throw (ClientException) + */ +void Repository::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas)throw (ClientException) +{ + svn_error_t * error = m_Data->dump(output,start,end,incremental,use_deltas); + if (error!=0) { + throw ClientException (error); + } +} + +void Repository::loaddump(const QString&dump,LOAD_UUID uuida, const QString&parentFolder, bool usePre, bool usePost)throw (ClientException) +{ + svn_repos_load_uuid uuid_action; + switch (uuida) { + case UUID_IGNORE_ACTION: + uuid_action=svn_repos_load_uuid_ignore; + break; + case UUID_FORCE_ACTION: + uuid_action=svn_repos_load_uuid_force ; + break; + case UUID_DEFAULT_ACTION: + default: + uuid_action=svn_repos_load_uuid_default; + break; + } + svn_error_t * error = m_Data->loaddump(dump,uuid_action,parentFolder,usePre,usePost); + if (error!=0) { + throw ClientException (error); + } +} + +/*! + \fn svn::Repository::hotcopy(const QString&src,const QString&dest,bool cleanlogs) + */ +void Repository::hotcopy(const QString&src,const QString&dest,bool cleanlogs)throw (ClientException) +{ + svn_error_t * error = RepositoryData::hotcopy(src,dest,cleanlogs); + if (error!=0) { + throw ClientException (error); + } +} + +} // namespace repository + +} // namespace svn diff --git a/src/svnqt/repository.hpp b/src/svnqt/repository.hpp new file mode 100644 index 0000000..e4ea5eb --- /dev/null +++ b/src/svnqt/repository.hpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNREPOSITORY_H +#define SVNREPOSITORY_H + +// Ignore MSVC 7, 2005 & 2008 compiler warning: C++ exception specification +#if defined (_MSC_VER) && _MSC_VER > 1200 && _MSC_VER <= 1550 +#pragma warning (disable: 4290) +#endif + +#include "svnqt/exception.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +namespace svn { + +namespace repository { + +class RepositoryData; +class RepositoryListener; + +//! wrapper class for subversions administrative repository functions +/*! + \author Rajko Albrecht <ral@alwins-world.de> +*/ +class SVNQT_EXPORT Repository{ +public: + enum LOAD_UUID { + UUID_DEFAULT_ACTION = 0, + UUID_IGNORE_ACTION = 1, + UUID_FORCE_ACTION = 2 + }; + //! constructor + /*! + * \param aListener callback object, the object will NOT take the ownership. + */ + Repository(svn::repository::RepositoryListener*aListener); + //! destructor + virtual ~Repository(); + + //! open a local repository path for maintainance + /*! + Assigns a repository with that object. If a path was opened before it will closed. + \param path Path to a local repository, must not be an url + \exception ClientException will be thrown in case of an error + */ + void Open(const QString&path) throw (ClientException); + //! Creates and open a new repository + /*! + * Creates a new repository in path with type fstype. If create succeeded open and assigns with the object. + * If a repository was opened before it will closed. + * \param path the path where to create the new repository. Must not be an url. + * \param fstype type of repository ("fsfs" or "bdb"). If wrong is set fsfs is the default. + * \param _bdbnosync disable fsync at transaction commit [Berkeley DB] + * \param _bdbautologremove enable automatic log file removal [Berkeley DB] + * \param _pre_1_4_compat Create repository compatibel to version earlier than 1.4 (only used with subversion 1.4) + */ + void CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync = false, + bool _bdbautologremove = true, bool _pre_1_4_compat=false, bool _pre_1_5_compat=false) throw (ClientException); + //! dump content of repository to a file + /*! + The repository must opend before. Progress message go trough the assigned svn::repository::RepositoryListener object. + The revision parameter must be numbers, no constant values like svn::Revision::HEAD. + \param output where to output the content + \param start Begin on revision. If revision == -1 than start with first entry. + \param end End with revision. If revision == -1 than end with current head. + \param incremental dump incrementally + \param use_deltas use deltas in dump output + \exception ClientException will be thrown in case of an error + */ + void dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas)throw (ClientException); + //! load a dump into repository + /*! + The repository must opened before. Progress message go trough the assigned svn::repository::RepositoryListener object. + \param dump Dumpfile to load + \param uuida what to do with UUIDs + \param parentFolder put content of dumpstream within folder in repository, if empty put into root-folder. + \param usePre use pre-commit-hook + \param usePost use post-commit-hook + \exception ClientException will be thrown in case of an error + */ + void loaddump(const QString&dump,LOAD_UUID uuida, const QString&parentFolder, bool usePre, bool usePost)throw (ClientException); + //! copy a repository to a new location + /*! + \param src the repository path to copy + \param dest where to copy + \param cleanlogs remove redundand log files from source + \exception ClientException will be thrown in case of an error + */ + static void hotcopy(const QString&src,const QString&dest,bool cleanlogs)throw (ClientException); + +private: + RepositoryData*m_Data; +}; + +} + +} + +#endif diff --git a/src/svnqt/repositorydata.cpp b/src/svnqt/repositorydata.cpp new file mode 100644 index 0000000..2ab9c5d --- /dev/null +++ b/src/svnqt/repositorydata.cpp @@ -0,0 +1,250 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnqt/repositorydata.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/exception.hpp" +#include "svnqt/repositorylistener.hpp" +#include "svnqt/svnfilestream.hpp" + +#include <svn_fs.h> +#include <svn_path.h> +#include <svn_config.h> + +namespace svn { + +namespace repository { + +class RepoOutStream:public stream::SvnStream +{ +public: + RepoOutStream(RepositoryData*); + virtual ~RepoOutStream(){} + + virtual bool isOk()const{return true;} + virtual long write(const char*data,const unsigned long max); + +protected: + RepositoryData*m_Back; +}; + +RepoOutStream::RepoOutStream(RepositoryData*aBack) + : SvnStream(false,true) +{ + m_Back = aBack; +} + +long RepoOutStream::write(const char*data,const unsigned long max) +{ + if (m_Back) { + QString msg = QString::FROMUTF8(data,max); + m_Back->reposFsWarning(msg); + } + return max; +} + +RepositoryData::RepositoryData(RepositoryListener*aListener) +{ + m_Repository = 0; + m_Listener = aListener; +} + + +RepositoryData::~RepositoryData() +{ +} + +void RepositoryData::warning_func(void *baton, svn_error_t *err) +{ + RepositoryData*_r = (RepositoryData*)baton; + + if (_r) { + QString msg = svn::Exception::error2msg(err); + svn_error_clear(err); + _r->reposFsWarning(msg); + } +} + +void RepositoryData::reposFsWarning(const QString&msg) +{ + if (m_Listener) { + m_Listener->sendWarning(msg); + } +} + +svn_error_t*RepositoryData::cancel_func(void*baton) +{ + RepositoryListener*m_L = (RepositoryListener*)baton; + if (m_L && m_L->isCanceld()) { + return svn_error_create (SVN_ERR_CANCELLED, 0, QString::FROMUTF8("Cancelled by user.").TOUTF8()); + } + return SVN_NO_ERROR; +} + +/*! + \fn svn::RepositoryData::close() + */ +void RepositoryData::Close() +{ + m_Pool.renew(); + m_Repository = 0; +} + + +/*! + \fn svn::RepositoryData::Open(const QString&) + */ +svn_error_t * RepositoryData::Open(const QString&path) +{ + Close(); + svn_error_t * error = svn_repos_open(&m_Repository,path.TOUTF8(),m_Pool); + if (error!=0L) { + m_Repository=0; + return error; + } + svn_fs_set_warning_func(svn_repos_fs(m_Repository), RepositoryData::warning_func, this); + return SVN_NO_ERROR; +} + + +/*! + \fn svn::RepositoryData::CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync = false, bool _bdbautologremove = true, bool nosvn1diff=false) + */ +svn_error_t * RepositoryData::CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync, + bool _bdbautologremove, + bool _pre_1_4_compat, + bool _pre_1_5_compat) +{ + Close(); + const char* _type; +#if QT_VERSION < 0x040000 + if (fstype.lower()=="bdb") { +#else + if (fstype.toLower()=="bdb") { +#endif + _type="bdb"; + } else { + _type="fsfs"; + } + apr_hash_t *config; + apr_hash_t *fs_config = apr_hash_make(m_Pool); + + apr_hash_set(fs_config, SVN_FS_CONFIG_BDB_TXN_NOSYNC, + APR_HASH_KEY_STRING, + (_bdbnosync ? "1" : "0")); + apr_hash_set(fs_config, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE, + APR_HASH_KEY_STRING, + (_bdbautologremove ? "1" : "0")); + apr_hash_set(fs_config, SVN_FS_CONFIG_FS_TYPE, + APR_HASH_KEY_STRING, + _type); + +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 4) || SVN_VER_MAJOR>1) + if (_pre_1_4_compat) { + qDebug("Pre 14"); + apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE, + APR_HASH_KEY_STRING,"1"); + } +#else + Q_UNUSED(_pre_1_4_compat); +#endif +#if ((SVN_VER_MAJOR == 1) && (SVN_VER_MINOR >= 5) || SVN_VER_MAJOR>1) + if (_pre_1_5_compat) { + qDebug("Pre 15"); + apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE, + APR_HASH_KEY_STRING,"1"); + } +#else + Q_UNUSED(_pre_1_5_compat); +#endif + /// @todo config as extra paramter? Meanwhile default config only + /// (see svn::ContextData) + SVN_ERR(svn_config_get_config(&config, 0, m_Pool)); + const char*repository_path = apr_pstrdup (m_Pool,path.TOUTF8()); + + repository_path = svn_path_internal_style(repository_path, m_Pool); + + if (svn_path_is_url(repository_path)) { + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + "'%s' is an URL when it should be a path",repository_path); + } + SVN_ERR(svn_repos_create(&m_Repository, repository_path, + NULL, NULL,config, fs_config,m_Pool)); + + svn_fs_set_warning_func(svn_repos_fs(m_Repository), RepositoryData::warning_func, this); + + return SVN_NO_ERROR; +} + + +/*! + \fn svn::RepositoryData::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas) + */ +svn_error_t* RepositoryData::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas) +{ + if (!m_Repository) { + return svn_error_create(SVN_ERR_CANCELLED,0,"No repository selected."); + } + Pool pool; + svn::stream::SvnFileOStream out(output); + RepoOutStream backstream(this); + svn_revnum_t _s,_e; + _s = start.revnum(); + _e = end.revnum(); + SVN_ERR(svn_repos_dump_fs2(m_Repository,out,backstream,_s,_e,incremental,use_deltas, + RepositoryData::cancel_func,m_Listener,pool)); + + return SVN_NO_ERROR; +} + +svn_error_t* RepositoryData::loaddump(const QString&dump,svn_repos_load_uuid uuida, const QString&parentFolder, bool usePre, bool usePost) +{ + if (!m_Repository) { + return svn_error_create(SVN_ERR_CANCELLED,0,"No repository selected."); + } + svn::stream::SvnFileIStream infile(dump); + RepoOutStream backstream(this); + Pool pool; + const char*src_path = apr_pstrdup (pool,dump.TOUTF8()); + const char*dest_path; + if (parentFolder.isEmpty()) { + dest_path=0; + } else { + dest_path=apr_pstrdup (pool,parentFolder.TOUTF8()); + } + + src_path = svn_path_internal_style(src_path, pool); + SVN_ERR(svn_repos_load_fs2(m_Repository,infile,backstream,uuida,dest_path,usePre?1:0,usePost?1:0,RepositoryData::cancel_func,m_Listener,pool)); + return SVN_NO_ERROR; +} + +svn_error_t* RepositoryData::hotcopy(const QString&src,const QString&dest,bool cleanlogs) +{ + Pool pool; + const char*src_path = apr_pstrdup (pool,src.TOUTF8()); + const char*dest_path = apr_pstrdup (pool,dest.TOUTF8()); + src_path = svn_path_internal_style(src_path, pool); + dest_path = svn_path_internal_style(dest_path, pool); + SVN_ERR(svn_repos_hotcopy(src_path,dest_path,cleanlogs?1:0,pool)); + return SVN_NO_ERROR; +} + +} + +} diff --git a/src/svnqt/repositorydata.hpp b/src/svnqt/repositorydata.hpp new file mode 100644 index 0000000..9884b70 --- /dev/null +++ b/src/svnqt/repositorydata.hpp @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNREPOSITORYDATA_H +#define SVNREPOSITORYDATA_H + +#include "svnqt/pool.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/apr.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +#include <svn_repos.h> +#include <svn_error.h> + +namespace svn { + +namespace repository { + +class Repository; +class RepositoryListener; +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ +class SVNQT_NOEXPORT RepositoryData{ + friend class Repository; + +public: + RepositoryData(RepositoryListener*); + + virtual ~RepositoryData(); + void Close(); + svn_error_t * Open(const QString&); + svn_error_t * CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync = false, + bool _bdbautologremove = true, bool _pre_1_4_compat=false, bool _pre_1_5_compat=false); + + void reposFsWarning(const QString&msg); + svn_error_t* dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas); + svn_error_t* loaddump(const QString&dump,svn_repos_load_uuid uuida, const QString&parentFolder, bool usePre, bool usePost); + static svn_error_t* hotcopy(const QString&src,const QString&dest,bool cleanlogs); + +protected: + Pool m_Pool; + svn_repos_t*m_Repository; + RepositoryListener*m_Listener; + +private: + static void warning_func(void *baton, svn_error_t *err); + static svn_error_t*cancel_func(void*baton); +}; + +} + +} + +#endif diff --git a/src/svnqt/repositorylistener.cpp b/src/svnqt/repositorylistener.cpp new file mode 100644 index 0000000..9c809a8 --- /dev/null +++ b/src/svnqt/repositorylistener.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "repositorylistener.hpp" + +namespace svn { + +namespace repository { + +RepositoryListener::RepositoryListener() +{ +} + + +RepositoryListener::~RepositoryListener() +{ +} + +} + +} diff --git a/src/svnqt/repositorylistener.hpp b/src/svnqt/repositorylistener.hpp new file mode 100644 index 0000000..15d650d --- /dev/null +++ b/src/svnqt/repositorylistener.hpp @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef REPOSITORYLISTENER_HPP +#define REPOSITORYLISTENER_HPP + +/** + @author Rajko Albrecht <ral@alwins-world.de> +*/ + +#include "svnqt/svnqt_defines.hpp" +#include <qstring.h> + +namespace svn { + +namespace repository { + +//! class for callbacks on repository operations +class SVNQT_EXPORT RepositoryListener{ + +public: + //! constructor + RepositoryListener(); + //! destructor + virtual ~RepositoryListener(); + + //! sends a warning or informative message + virtual void sendWarning(const QString&)=0; + //! sends an error message + virtual void sendError(const QString&)=0; + //! check if running operation should cancelled + virtual bool isCanceld() =0; + +}; + +} + +} + +#endif diff --git a/src/svnqt/revision.cpp b/src/svnqt/revision.cpp new file mode 100644 index 0000000..a89fae1 --- /dev/null +++ b/src/svnqt/revision.cpp @@ -0,0 +1,299 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + + +// svncpp +#include "revision.hpp" +#include "pool.hpp" + +// qt +#include "qdatetime.h" + +namespace svn +{ + const svn_opt_revision_kind Revision::START = svn_opt_revision_number; + const svn_opt_revision_kind Revision::BASE = svn_opt_revision_base; + const svn_opt_revision_kind Revision::HEAD = svn_opt_revision_head; + const svn_opt_revision_kind Revision::WORKING = svn_opt_revision_working; + const svn_opt_revision_kind Revision::UNDEFINED = svn_opt_revision_unspecified; + const svn_opt_revision_kind Revision::PREV = svn_opt_revision_previous; + + const svn_opt_revision_kind Revision::DATE = svn_opt_revision_date; + const svn_opt_revision_kind Revision::NUMBER = Revision::START; + + + Revision::Revision (const svn_opt_revision_t * revision) + { + init (revision); + } + + Revision::Revision (const svn_revnum_t revnum) + { + if (revnum<0) { + m_revision.kind = svn_opt_revision_unspecified; + m_revision.value.number = 0; + } else { + m_revision.kind = svn_opt_revision_number; + m_revision.value.number = revnum; + } + } + + Revision::Revision (const svn_opt_revision_kind kind) + { + m_revision.kind = kind; + m_revision.value.number = 0; + } + + Revision::Revision (const int revnum, const QString&revstring) + { + m_revision.kind = svn_opt_revision_unspecified; + + if (revnum > -1) { + m_revision.kind = svn_opt_revision_number; + m_revision.value.number = revnum; + } else { + assign(revstring); + } + } + + Revision::Revision (const QString&revstring) + { + assign(revstring); + } + + void + Revision::assign(const QString&revstring) + { + m_revision.kind = svn_opt_revision_unspecified; + if (revstring.isEmpty()) { + return; + } + if (revstring=="WORKING") { + m_revision.kind = WORKING; + } else if (revstring=="BASE") { + m_revision.kind = BASE; + } else if (revstring=="START"){ + m_revision.kind = Revision::START; + m_revision.value.number = 0; + } else if (revstring=="PREV"){ + m_revision.kind = Revision::PREV; + } else if (!revstring.isNull()) { + Pool pool; + svn_opt_revision_t endrev; + svn_opt_parse_revision(&m_revision,&endrev,revstring.TOUTF8(),pool); + } + } + + void + Revision::assign(const QDateTime&dateTime) + { + m_revision.kind = svn_opt_revision_date; + DateTime dt(dateTime); + m_revision.value.date = dt.GetAPRTimeT(); + } + + Revision& Revision::operator=(const QString&what) + { + assign(what); + return *this; + } + + Revision::Revision (const DateTime dateTime) + { + m_revision.kind = svn_opt_revision_date; + m_revision.value.date = dateTime.GetAPRTimeT(); + } + + Revision::Revision (const QDateTime&dateTime) + { + assign(dateTime); + } + + Revision::Revision (const Revision & revision) + { + init (revision.revision ()); + } + + void + Revision::init (const svn_opt_revision_t * revision) + { + if( !revision ) + { + m_revision.kind = svn_opt_revision_unspecified; + } + else + { + m_revision.kind = revision->kind; + + // m_revision.value is a union so we are not + // allowed to set number if we want to use date + // and vice versa + + switch( revision->kind ) + { + case svn_opt_revision_number: + m_revision.value.number = revision->value.number; + break; + + case svn_opt_revision_date: + m_revision.value.date = revision->value.date; + break; + + default: + m_revision.value.number = 0; + } + } + } + + Revision::operator QString ()const + { + return toString(); + } + + QString Revision::toString()const + { + QString value; + QDateTime result; + switch (m_revision.kind) { + case svn_opt_revision_number: + value.sprintf("%li",m_revision.value.number); + break; + case svn_opt_revision_date: + value = DateTime(m_revision.value.date).toString("{yyyy-MM-dd}"); + break; + case svn_opt_revision_base: + value = "BASE"; + break; + case svn_opt_revision_head: + value = "HEAD"; + break; + case svn_opt_revision_working: + value = "WORKING"; + break; + case svn_opt_revision_previous: + value="PREVIOUS"; + break; + case svn_opt_revision_unspecified: + default: + value="-1"; + break; + } + return value; + } + + const svn_opt_revision_t * + Revision::revision () const + { + return &m_revision; + } + + svn_revnum_t + Revision::revnum () const + { + if (m_revision.kind==svn_opt_revision_number) { + return m_revision.value.number; + } + return SVN_INVALID_REVNUM; + } + + apr_time_t + Revision::date () const + { + return m_revision.value.date; + } + + svn_opt_revision_kind + Revision::kind () const + { + return m_revision.kind; + } + + bool Revision::operator==(const Revision&r)const + { + if (r.kind()!=kind()) { + return false; + } + if (m_revision.kind == svn_opt_revision_number) { + return revnum()==r.revnum(); + } else if (m_revision.kind == svn_opt_revision_date) { + return date()==r.date(); + } + return true; + } + + bool Revision::operator==(int value)const + { + if (m_revision.kind!=svn_opt_revision_number || value!=revnum()) { + return false; + } + return true; + } + + bool Revision::operator!=(const svn_opt_revision_kind t)const + { + return kind()!=t; + } + bool Revision::operator==(const svn_opt_revision_kind t)const + { + return kind()==t; + } + + bool Revision::operator!()const + { + return kind()==UNDEFINED; + } + + bool Revision::operator!() + { + return kind()==UNDEFINED; + } + + Revision::operator bool()const + { + return kind()!=UNDEFINED; + } + + Revision::operator bool() + { + return kind()!=UNDEFINED; + } + + bool Revision::isRemote()const + { + return kind()!=UNDEFINED && kind()!=BASE && kind()!=WORKING; + } + +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/revision.hpp b/src/svnqt/revision.hpp new file mode 100644 index 0000000..371b1a1 --- /dev/null +++ b/src/svnqt/revision.hpp @@ -0,0 +1,222 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_REVISION_HPP_ +#define _SVNCPP_REVISION_HPP_ + +// svncpp +#include <svnqt/datetime.hpp> +#include <svnqt/svnqt_defines.hpp> + +// qt +#include <qglobal.h> +#if QT_VERSION < 0x040000 + #include <qstring.h> + #include <qtextstream.h> +#else + #include <QtCore> +#endif + +// subversion api +#include "svn_types.h" +#include "svn_opt.h" + +namespace svn +{ + /** + * Class that encapsulates svn_opt_revnum_t. + * + * @see svn_opt_revnum_t + */ + class SVNQT_EXPORT Revision + { + private: + svn_opt_revision_t m_revision; + + void + init (const svn_opt_revision_t * revision); + + void + assign(const QString&); + + void + assign(const QDateTime&); + + public: + static const svn_opt_revision_kind START; + static const svn_opt_revision_kind BASE; + static const svn_opt_revision_kind HEAD; + static const svn_opt_revision_kind WORKING; + static const svn_opt_revision_kind UNDEFINED; + static const svn_opt_revision_kind PREV; + + static const svn_opt_revision_kind DATE; + static const svn_opt_revision_kind NUMBER; + + /** + * Constructor + * + * @param revision revision information + */ + Revision (const svn_opt_revision_t * revision); + + /** + * Constructor + * + * @param revnum revision number + */ + Revision (const svn_revnum_t revnum); + + /** + * Constructor + * @param revnum a revision number + * @param revstring a revision string + * + * The revision string MUST uppercase, it may some of "HEAD", "BASE", "WORKING", "COMMITED", "PREV", + * or a date in form {YYYY-MM-DD}. + */ + Revision (const int revnum, const QString&revstring); + + /** + * Constructor + * @param revstring a revision string + * + * The revision string MUST uppercase, it may some of "HEAD", "BASE", "WORKING", "COMMITED", "PREV", + * or a date in form {YYYY-MM-DD}. + */ + Revision (const QString&revstring); + + /** + * Constructor + * + * @param kind + */ + Revision (const svn_opt_revision_kind kind = svn_opt_revision_unspecified); + + /** + * Constructor + * + * @param dateTime DateTime wrapper for apr_time_t + * @todo change it to referenced parameter (requires interface upgrade of lib) + */ + Revision (const DateTime dateTime); + /** + * Constructor + * + * @param dateTime QDateTime type + */ + Revision (const QDateTime&dateTime); + + /** + * Copy constructor + * + * @param revision Source + */ + Revision (const Revision & revision); + + /** + * @return revision information + */ + const svn_opt_revision_t * + revision () const; + + /** + * @see revision (). Same function + * but with operator overloading + */ + operator svn_opt_revision_t * () + { + return &m_revision; + } + + /** + * @see revision (). Same function + * but with operator overloading + */ + operator const svn_opt_revision_t*()const + { + return &m_revision; + } + + /** + * @return revision numver + */ + svn_revnum_t + revnum () const; + + /** + * @return revision kind + */ + svn_opt_revision_kind + kind () const; + + operator QString ()const; + QString toString()const; + + bool isRemote()const; + + /** + * @return date + */ + apr_time_t + date () const; + + bool operator==(const Revision&)const; + bool operator!=(const svn_opt_revision_kind)const; + bool operator==(const svn_opt_revision_kind)const; + bool operator==(int)const; + + bool operator!()const; + bool operator!(); + operator bool()const; + operator bool(); + + /** + * assignment operator + * @param what a simple revision string (not s:e but s) + * @return object itself + */ + Revision& operator=(const QString&what); + + }; +} + +inline QTextStream& operator<<(QTextStream&s,svn::Revision&r) +{ + s << r.toString(); + return s; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/shared_pointer.hpp b/src/svnqt/shared_pointer.hpp new file mode 100644 index 0000000..cd1587e --- /dev/null +++ b/src/svnqt/shared_pointer.hpp @@ -0,0 +1,193 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef SVNQT_SHARED_POINTER_HPP +#define SVNQT_SHARED_POINTER_HPP + +#include "svnqt/smart_pointer.hpp" + +/*! + * \file shared_pointer.hpp + * \brief shared pointer adapter + * \sa smart_pointer.hpp + */ + +namespace svn +{ + +template<class T> class SharedPointer; + +/*! + * Data container for svn::SharedPointer + */ +template<class T> class SharedPointerData:public ref_count +{ + friend class SharedPointer<T>; +protected: + //! The protected pointer + T*data; +public: + //! Constructor + /*! + * Take ownership of pointer dt + * \param dt the data to wrap + **/ + SharedPointerData(T*dt){ + data = dt; + } + //! Destructor + /*! + * Release content data + */ + ~SharedPointerData() { + delete data; + } +}; + +//! Shared pointer adapater +/*! + * Implements a thread safe reference counter around any pointer. + * This class takes ownership of data, eg., last reference will delete + * the data it inspects. + */ +template<class T> class SharedPointer +{ + typedef SharedPointerData<T> Data; + Data*data; + + //! count down reference of data and release if it was the last share + void unref(){ + if (data) { + data->Decr(); + if (!data->Shared()) { + delete data; + } + data = 0; + } + } +public: + //! empty constructor + SharedPointer():data(0){} + //! copy constructor + /*! + * \param p Data to increase reference for + */ + SharedPointer(const SharedPointer<T>& p) + { + if ( (data = p.data) ) data->Incr(); + } + //! assignment constructor + /*! + * Take ownership of data pointer t + * \param t data pointer to store inside + */ + SharedPointer(T*t) + { + data = new Data(t);data->Incr(); + } + //! destructor + /*! + * decrease reference, if reference == 0 release data + */ + ~SharedPointer() + { + unref(); + } + + //! assignment operator + /*! + * \param p Data to increase reference for + */ + SharedPointer<T> &operator=(const SharedPointer<T>&p) + { + // we always have a reference to the data + if (data==p.data) return *this; + unref(); + if ((data=p.data)) data->Incr(); + return *this; + } + //! assignment operator + /*! + * \param p Data to increase reference for + */ + SharedPointer<T> &operator=(T*p) + { + if (data && data->data==p) { + return *this; + } + unref(); + data = new Data(p); + data->Incr(); + return *this; + } + + //! access operator + /*! + * Use this operator with care! + * \return pointer to wrapped data + */ + operator T*()const {return data->data;} + //! access operator + /*! + * \return reference to wrapped data + */ + T& operator*() {return *data->data;} + //! access operator + /*! + * \return const reference to wrapped data + */ + const T& operator*()const{return *data->data;} + //! access operator + /*! + * \return pointer to wrapped data + */ + T*operator->() {return data->data;} + //! access operator + /*! + * \return const pointer to wrapped data + */ + const T*operator->()const{return data->data;} + + //! Bool operator + /*! + * \return true if content set and not a null-pointer, otherwise false + */ + operator bool () const { return (data != 0 && data->data != 0); } + //! Bool operator + /*! + * \return true if content set and not a null-pointer, otherwise false + */ + operator bool () { return ( data != 0 && data->data != 0 );} + + //! Negation operator + /*! + * \return true if content not set or a null-pointer, otherwise false + */ + bool operator! () const { return (data == 0 || data->data == 0); } + //! Negation operator + /*! + * \return true if content not set or a null-pointer, otherwise false + */ + bool operator! () { return (data == 0 || data->data == 0); } +}; + +} + +#endif diff --git a/src/svnqt/smart_pointer.hpp b/src/svnqt/smart_pointer.hpp new file mode 100644 index 0000000..2790df5 --- /dev/null +++ b/src/svnqt/smart_pointer.hpp @@ -0,0 +1,146 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef _smart_pointer_hpp +#define _smart_pointer_hpp + +#if defined QT_THREAD_SUPPORT +#include "qmutex.h" +#endif + +#include "svnqt/svnqt_defines.hpp" + +/*! + * \file smart_pointer.h + * \brief smart pointer and reference counter + * \author Rajko Albrecht + * + */ + +namespace svn +{ + +//! simple reference counter class +class ref_count { +protected: + //! reference count member + long m_RefCount; +#ifdef QT_THREAD_SUPPORT + QMutex m_RefcountMutex; +#endif +public: + //! first reference must be added after "new" via Pointer() + ref_count() : m_RefCount(0) +#ifdef QT_THREAD_SUPPORT + ,m_RefcountMutex() +#endif + {} + virtual ~ref_count() {} + //! add a reference + void Incr() { +#ifdef QT_THREAD_SUPPORT + QMutexLocker a(&m_RefcountMutex); +#endif + ++m_RefCount; + } + //! delete a reference + bool Decr() { +#ifdef QT_THREAD_SUPPORT + QMutexLocker a(&m_RefcountMutex); +#endif + --m_RefCount; + return Shared(); + } + //! is it referenced + bool Shared() { return (m_RefCount > 0); } +}; + +//! reference counting wrapper class +template<class T> class smart_pointer { + //! pointer to object + /*! + * this object must contain Incr(), Decr() and Shared() + * methode as public members. The best way is, that it will be a child + * class of RefCount + */ + T *ptr; +public: + //! standart constructor + smart_pointer() { ptr = 0; } + //! standart destructor + /*! + * release the reference, if it were the last reference, destroys + * ptr + */ + ~smart_pointer() + { + if (ptr && !ptr->Decr()) { + delete ptr; + } + } + //! construction + smart_pointer(T* t) { if ( (ptr = t) ) ptr->Incr(); } + //! Pointer copy + smart_pointer(const smart_pointer<T>& p) + { if ( (ptr = p.ptr) ) ptr->Incr(); } + //! pointer copy by assignment + smart_pointer<T>& operator= (const smart_pointer<T>& p) + { + // already same: nothing to do + if (ptr == p.ptr) return *this; + // decouple reference + if ( ptr && !ptr->Decr()) delete ptr; + // establish new reference + if ( (ptr = p.ptr) ) ptr->Incr(); + return *this; + } + smart_pointer<T>& operator= (T*p) + { + if (ptr==p)return *this; + if (ptr && !ptr->Decr()) delete ptr; + if ( (ptr=p) ) ptr->Incr(); + return *this; + } + + //! cast to conventional pointer + operator T* () const { return ptr; } + + //! deref: fails for 0 pointer + T& operator* () {return *ptr; } + //! deref: fails for 0 pointer + const T& operator* ()const {return *ptr; } + + //! deref with method call + T* operator-> () {return ptr; } + //! deref with const method call + const T* operator-> ()const {return ptr; } + + //! supports "if (pointer)" + operator bool () const { return (ptr != 0); } + //! "if (pointer)" as non const + operator bool () { return ptr != 0;} + + //! support if (!pointer)" + bool operator! () const { return (ptr == 0); } + //! support if (!pointer)" as non const + bool operator! () { return (ptr == 0); } +}; + +} // namespace svn +#endif diff --git a/src/svnqt/status.cpp b/src/svnqt/status.cpp new file mode 100644 index 0000000..15a4af0 --- /dev/null +++ b/src/svnqt/status.cpp @@ -0,0 +1,319 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// svncpp +#include "status.hpp" +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/path.hpp" +#include "svnqt/url.hpp" + +#include "svn_path.h" + +namespace svn +{ + class SVNQT_NOEXPORT Status_private + { + public: + Status_private(); + virtual ~Status_private(); + /** + * Initialize structures + * + * @param path + * @param status if NULL isVersioned will be false + */ + void + init (const QString&path, const svn_wc_status2_t * status); + void + init (const QString&path,const Status_private&src); + void + init(const QString&url,const DirEntryPtr&src); + void + init(const QString&url,const InfoEntry&src); + + void setPath(const QString&); + + QString m_Path; + bool m_isVersioned; + bool m_hasReal; + LockEntry m_Lock; + Entry m_entry; + + svn_wc_status_kind _text_status,_prop_status,_repos_text_status,_repos_prop_status; + bool _copied,_switched; + }; + + Status_private::Status_private() + :m_Path(),m_isVersioned(false),m_hasReal(false) + { + } + + Status_private::~ Status_private() + { + } + + void Status_private::setPath(const QString&aPath) + { + Pool pool; + if (!Url::isValid(aPath)) { + m_Path = aPath; + } else { + const char * int_path = svn_path_uri_decode(aPath.TOUTF8(), pool.pool () ); + m_Path = QString::FROMUTF8(int_path); + } + } + + void Status_private::init (const QString&path, const svn_wc_status2_t * status) + { + setPath(path); + if (!status) + { + m_isVersioned = false; + m_hasReal = false; + m_entry=Entry(); + m_Lock = LockEntry(); + } + else + { + m_isVersioned = status->text_status > svn_wc_status_unversioned||status->repos_text_status>svn_wc_status_unversioned; + m_hasReal = m_isVersioned && + status->text_status!=svn_wc_status_ignored; + // now duplicate the contents + if (status->entry) + { + m_entry = Entry(status->entry); + } else { + m_entry=Entry(); + } + _text_status = status->text_status; + _prop_status = status->prop_status; + _copied = status->copied!=0; + _switched = status->switched!=0; + _repos_text_status = status->repos_text_status; + _repos_prop_status = status->repos_prop_status; + if (status->repos_lock) { + m_Lock.init(status->repos_lock->creation_date, + status->repos_lock->expiration_date, + status->repos_lock->owner, + status->repos_lock->comment, + status->repos_lock->token); + } else { + m_Lock=LockEntry(); + } + } + } + + void + Status_private::init (const QString&path,const Status_private&src) + { + setPath(path); + m_Lock=src.m_Lock; + m_entry=src.m_entry; + m_isVersioned=src.m_isVersioned; + m_hasReal=src.m_hasReal; + _text_status=src._text_status; + _prop_status=src._prop_status; + _repos_text_status=src._repos_text_status; + _repos_prop_status=src._repos_prop_status; + _copied=src._copied; + _switched=src._switched; + } + + void Status_private::init(const QString&url,const DirEntryPtr&src) + { + m_entry=Entry(url,src); + setPath(url); + _text_status = svn_wc_status_normal; + _prop_status = svn_wc_status_normal; + if (src) { + m_Lock=src->lockEntry(); + m_isVersioned=true; + m_hasReal=true; + } + _switched = false; + _repos_text_status = svn_wc_status_normal; + _repos_prop_status = svn_wc_status_normal; + } + + void Status_private::init(const QString&url,const InfoEntry&src) + { + m_entry=Entry(url,src); + setPath(url); + m_Lock=src.lockEntry(); + _text_status = svn_wc_status_normal; + _prop_status = svn_wc_status_normal; + _repos_text_status = svn_wc_status_normal; + _repos_prop_status = svn_wc_status_normal; + m_isVersioned=true; + m_hasReal=true; + } + + Status::Status (const Status & src) + : m_Data(new Status_private()) + { + if( &src != this ) + { + if (src.m_Data) { + m_Data->init (src.m_Data->m_Path, *(src.m_Data)); + } else { + m_Data->init(src.m_Data->m_Path,0); + } + } + } + + Status::Status (const QString&path, svn_wc_status2_t * status) + : m_Data(new Status_private()) + { + m_Data->init(path, status); + } + + Status::Status (const char*path, svn_wc_status2_t * status) + : m_Data(new Status_private()) + { + m_Data->init(QString::FROMUTF8(path),status); + } + + Status::Status(const QString&url,const DirEntryPtr&src) + : m_Data(new Status_private()) + { + m_Data->init(url,src); + } + + Status::Status(const QString&url,const InfoEntry&src) + : m_Data(new Status_private()) + { + m_Data->init(url,src); + } + + Status::~Status () + { + delete m_Data; + } + + Status & + Status::operator=(const Status & status) + { + if (this == &status) + return *this; + if (status.m_Data) { + m_Data->init (status.m_Data->m_Path, *(status.m_Data)); + } else { + m_Data->init(status.m_Data->m_Path,0); + } + return *this; + } + + const LockEntry& + Status::lockEntry () const + { + return m_Data->m_Lock; + } + svn_wc_status_kind + Status::reposPropStatus () const + { + return m_Data->_repos_prop_status; + } + svn_wc_status_kind + Status::reposTextStatus () const + { + return m_Data->_repos_text_status; + } + bool + Status::isSwitched () const + { + return m_Data->_switched != 0; + } + bool + Status::isCopied () const + { + return m_Data->_copied; + } + + bool + Status::isLocked () const + { + return m_Data->m_Lock.Locked(); + } + + bool + Status::isModified()const + { + return textStatus()==svn_wc_status_modified||propStatus()==svn_wc_status_modified + ||textStatus ()==svn_wc_status_replaced; + } + + bool + Status::isRealVersioned()const + { + return m_Data->m_hasReal; + } + + bool + Status::isVersioned () const + { + return m_Data->m_isVersioned; + } + + svn_wc_status_kind + Status::propStatus () const + { + return m_Data->_prop_status; + } + + svn_wc_status_kind + Status::textStatus () const + { + return m_Data->_text_status; + } + + const Entry& + Status::entry () const + { + return m_Data->m_entry; + } + + const QString& + Status::path () const + { + return m_Data->m_Path; + } + + bool + Status::validReposStatus()const + { + return reposTextStatus()!=svn_wc_status_none||reposPropStatus()!=svn_wc_status_none; + } + + bool + Status::validLocalStatus()const + { + return textStatus()!=svn_wc_status_none||propStatus()!=svn_wc_status_none; + } +} diff --git a/src/svnqt/status.hpp b/src/svnqt/status.hpp new file mode 100644 index 0000000..ec0f436 --- /dev/null +++ b/src/svnqt/status.hpp @@ -0,0 +1,187 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#ifndef _SVNCPP_STATUS_HPP_ +#define _SVNCPP_STATUS_HPP_ + +// subversion api +#include "svn_wc.h" + +// svncpp +#include "svnqt/svnqttypes.hpp" +#include "svnqt/entry.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/lock_entry.hpp" +#include "svnqt/dirent.hpp" +#include "svnqt/info_entry.hpp" +#include "svnqt/svnqt_defines.hpp" + +namespace svn +{ + /** + * Subversion status API. This class wraps around + * @a svn_wc_status_t. + * + * @see svn_wc.hpp + * @see svn_wc_status_t + */ + class Status_private; + + class SVNQT_EXPORT Status + { + public: + /** + * copy constructor + */ + Status (const Status & src); + + /** + * default constructor + * + * @param path path for this status entry + * @param status status entry + */ + Status (const QString&path=QString::null, svn_wc_status2_t * status = NULL); + /** + * default constructor + * + * @param path path for this status entry + * @param status status entry + */ + Status (const char*path, svn_wc_status2_t * status = NULL); + /** + * converting constructor + */ + Status(const QString&path,const DirEntryPtr&src); + /** + * converting constructor + */ + Status(const QString&path,const InfoEntry&src); + + /** + * destructor + */ + virtual ~Status (); + + /** + * @return path of status entry + */ + const QString& + path () const; + + /** + * @return entry for this path + * @retval entry.isValid () = false item is not versioned + */ + const Entry& + entry () const; + /** + * @return file status property enum of the "textual" component. + */ + svn_wc_status_kind + textStatus () const; + + /** + * @return file status property enum of the "property" component. + */ + svn_wc_status_kind + propStatus () const; + + /** + * @retval TRUE if under version control + */ + bool + isVersioned () const; + + /** + * @retval TRUE if under version control and not ignored + */ + bool + isRealVersioned()const; + + /** + * @retval TRUE if under version control and local modified + */ + bool + isModified()const; + + /** + * @retval TRUE if locked + */ + bool + isLocked () const; + + /** + * @retval TRUE if copied + */ + bool + isCopied () const; + + /** + * @retval TRUE if switched + */ + bool + isSwitched () const; + /** + * @return the entry's text status in the repository + */ + svn_wc_status_kind + reposTextStatus () const; + /** + * @return the entry's prop status in the repository + */ + svn_wc_status_kind + reposPropStatus () const; + + const LockEntry& + lockEntry () const; + + bool + validReposStatus()const; + + bool + validLocalStatus()const; + + + /** + * assignment operator + */ + Status & + operator = (const Status &); + private: + Status_private*m_Data; + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/stringarray.cpp b/src/svnqt/stringarray.cpp new file mode 100644 index 0000000..bdac55b --- /dev/null +++ b/src/svnqt/stringarray.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + * Copyright (C) 2006-2008 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "svnqt/stringarray.hpp" +#include "svnqt/pool.hpp" + +#include <svn_types.h> +// apr api +#include <apr_pools.h> +#include <apr_strings.h> + +/*! + \fn svn::StringArray::StringArray() + */ + svn::StringArray::StringArray() + :m_content() +{ + setNull(true); +} + + +/*! + \fn svn::StringArray::StringArray(const QStringList&) + */ +svn::StringArray::StringArray(const QStringList&aList) + :m_content(aList) +{ + setNull(false); +} + +/*! + \fn svn::StringArray::StringArray(const apr_array_header_t * apr_targets) + */ +svn::StringArray::StringArray(const apr_array_header_t * apr_targets) + :m_content() +{ + int i; + for (i = 0; i < apr_targets->nelts; i++) + { + const char ** target = + &APR_ARRAY_IDX (apr_targets, i, const char *); + + m_content.push_back (QString::FROMUTF8(*target)); + } +} + + +/*! + \fn svn::StringArray::size()const + */ +size_t svn::StringArray::size()const +{ + if (isNull()) { + return 0; + } + return m_content.size (); +} + + +/*! + \fn svn::StringArray::operator[](size_t which) + */ +const QString& svn::StringArray::operator[](size_t which) +{ + return m_content[which]; +} + + +/*! + \fn svn::StringArray::array (const Pool & pool) const + */ +apr_array_header_t * svn::StringArray::array (const Pool & pool) const +{ + if (isNull()) { + return 0; + } + QStringList::const_iterator it; + + apr_pool_t *apr_pool = pool.pool (); + apr_array_header_t *apr_targets = + apr_array_make (apr_pool,m_content.size(),sizeof (const char *)); + + for (it = m_content.begin (); it != m_content.end (); it++) + { + QByteArray s = (*it).TOUTF8(); + char * t2 = apr_pstrndup (apr_pool,s,s.size()); + + (*((const char **) apr_array_push (apr_targets))) = t2; + } + return apr_targets; +} + +bool svn::StringArray::isNull()const +{ + return m_isNull; +} + +void svn::StringArray::setNull(bool _n) +{ + if (_n) { + m_content.clear(); + } + m_isNull = _n; +} diff --git a/src/svnqt/stringarray.hpp b/src/svnqt/stringarray.hpp new file mode 100644 index 0000000..285f500 --- /dev/null +++ b/src/svnqt/stringarray.hpp @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2006-2008 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _STRING_ARRAY_HPP +#define _STRING_ARRAY_HPP + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" + +#include <qglobal.h> +#if QT_VERSION < 0x040000 +#include <qstringlist.h> +#else +#include <QtCore> +#include <QStringList> +#endif + +// apr api +#include "apr_tables.h" + +namespace svn +{ + // forward declarations + class Pool; + + /** Handle array of const char * in a c++ like way */ + class SVNQT_EXPORT StringArray + { + protected: + QStringList m_content; + bool m_isNull; + + public: + StringArray(); + StringArray(const QStringList&); + StringArray(const apr_array_header_t * apr_targets); + size_t size()const; + const QString& operator[](size_t which); + /** + * Returns an apr array containing char*. + * + * @param pool Pool used for conversion + */ + apr_array_header_t * array (const Pool & pool) const; + /** content of array + * @return const reference to data, may used for searches. + */ + const QStringList& data() const {return m_content;} + + /** if array should return 0 instead of empty array */ + bool isNull()const; + void setNull(bool _n); + }; +} + +#endif diff --git a/src/svnqt/svnfilestream.cpp b/src/svnqt/svnfilestream.cpp new file mode 100644 index 0000000..2803ef4 --- /dev/null +++ b/src/svnqt/svnfilestream.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnfilestream.hpp" + +#include <qfile.h> + +namespace svn { + +namespace stream { + +#if QT_VERSION < 0x040000 +typedef int openmode; +#define READONLY IO_ReadOnly +#define WRITEONLY IO_WriteOnly +#else +typedef QIODevice::OpenMode openmode; +#define READONLY QIODevice::ReadOnly +#define WRITEONLY QIODevice::WriteOnly +#endif + +class SVNQT_NOEXPORT SvnFileStream_private +{ +public: + SvnFileStream_private(const QString&fn,openmode mode); + virtual ~SvnFileStream_private(); + + QString m_FileName; + QFile m_File; +}; + +SvnFileStream_private::SvnFileStream_private(const QString&fn,openmode mode) + : m_FileName(fn),m_File(fn) +{ + m_File.open(mode); +} + +SvnFileStream_private::~SvnFileStream_private() +{ +} + +SvnFileOStream::SvnFileOStream(const QString&fn,svn_client_ctx_t*ctx) + :SvnStream(false,true,ctx) +{ + m_FileData = new SvnFileStream_private(fn,WRITEONLY); + if (!m_FileData->m_File.isOpen()) { + setError(m_FileData->m_File.errorString()); + } +} + + +SvnFileOStream::~SvnFileOStream() +{ + delete m_FileData; +} + + +bool SvnFileOStream::isOk() const +{ + return m_FileData->m_File.isOpen(); +} + +long SvnFileOStream::write(const char* data, const unsigned long max) +{ + if (!m_FileData->m_File.isOpen()) { + return -1; + } +#if QT_VERSION < 0x040000 + long res = m_FileData->m_File.writeBlock(data,max); +#else + long res = m_FileData->m_File.write(data,max); +#endif + if (res<0) { + setError(m_FileData->m_File.errorString()); + } + return res; +} + +SvnFileIStream::SvnFileIStream(const QString&fn,svn_client_ctx_t*ctx) + :SvnStream(true,false,ctx) +{ + m_FileData = new SvnFileStream_private(fn,READONLY); + if (!m_FileData->m_File.isOpen()) { + setError(m_FileData->m_File.errorString()); + } +} + + +SvnFileIStream::~SvnFileIStream() +{ + delete m_FileData; +} + + +bool SvnFileIStream::isOk() const +{ + return m_FileData->m_File.isOpen(); +} + +long SvnFileIStream::read(char* data, const unsigned long max) +{ + if (!m_FileData->m_File.isOpen()) { + return -1; + } +#if QT_VERSION < 0x040000 + long res = m_FileData->m_File.readBlock(data,max); +#else + long res = m_FileData->m_File.read(data,max); +#endif + if (res<0) { + setError(m_FileData->m_File.errorString()); + } + return res; +} + +} + +} diff --git a/src/svnqt/svnfilestream.hpp b/src/svnqt/svnfilestream.hpp new file mode 100644 index 0000000..d64e1cc --- /dev/null +++ b/src/svnqt/svnfilestream.hpp @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVN_STREAMSVNFILESTREAM_HPP +#define SVN_STREAMSVNFILESTREAM_HPP + +#include "svnstream.hpp" + +namespace svn { + +namespace stream { + +class SvnFileStream_private; + +/** + @author Rajko Albrecht <ral@alwins-world.de> + @short Writeonly filestream +*/ +class SVNQT_EXPORT SvnFileOStream : public SvnStream +{ +public: + SvnFileOStream(const QString&fn,svn_client_ctx_t*ctx=0); + + virtual ~SvnFileOStream(); + + virtual bool isOk() const; + virtual long write(const char* data, const unsigned long max); +private: + SvnFileStream_private*m_FileData; +}; + +/** + @author Rajko Albrecht <ral@alwins-world.de> + @short Readonly filestream +*/ +class SVNQT_EXPORT SvnFileIStream : public SvnStream +{ +public: + SvnFileIStream(const QString&fn,svn_client_ctx_t*ctx=0); + + virtual ~SvnFileIStream(); + virtual bool isOk() const; + virtual long read(char* data, const unsigned long max); + +private: + SvnFileStream_private*m_FileData; +}; + +} + +} + +#endif diff --git a/src/svnqt/svnqt_defines.hpp.in b/src/svnqt/svnqt_defines.hpp.in new file mode 100644 index 0000000..6281d42 --- /dev/null +++ b/src/svnqt/svnqt_defines.hpp.in @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _SVNQT_DEFINES_H +#define _SVNQT_DEFINES_H + +/* defines if we setup against a compiler with working "-fvisibility=hidden" */ +#define SVNQT_EXPORT @_SVNQT_EXPORT@ +#define SVNQT_NOEXPORT @_SVNQT_NOEXPORT@ + +/* cmake trick: so we make sure that the define in installs + is always set as in library used at build time + */ +#define TOUTF8 @TOUTF8@ +#define FROMUTF8 @FROMUTF8@ +#define QLIST @QLIST@ +#define TOASCII @TOASCII@ +#define HOMEDIR @HOMEDIR@ +#define QLONG @QLONG@ + +#define SVNQT_SIZE_UNKNOWN QLONG(-1) + +/* the difference between qt3 and qt4 is too much... :( */ +class QSqlDatabase; +typedef @QDATABASE@ QDataBase; +#endif diff --git a/src/svnqt/svnqttypes.hpp b/src/svnqt/svnqttypes.hpp new file mode 100644 index 0000000..b3c6381 --- /dev/null +++ b/src/svnqt/svnqttypes.hpp @@ -0,0 +1,104 @@ +/*************************************************************************** + * Copyright (C) 2007 by Rajko Albrecht ral@alwins-world.de * + * http://kdesvn.alwins-world.de/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _SVNQT_TYPES_HPP +#define _SVNQT_TYPES_HPP + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/shared_pointer.hpp" + +// qt +#include <qglobal.h> + +#if QT_VERSION < 0x040000 + #include <qstring.h> + #include <qpair.h> + #include <qvaluelist.h> + #include <qmap.h> +#else + #include <QtCore> +#endif + +namespace svn +{ + // forward declarations + class AnnotateLine; + class Context; + class DirEntry; + class InfoEntry; + class LogEntry; + class Revision; + class Status; + class Targets; + class Path; + class StringArray; + + typedef QLIST<AnnotateLine> AnnotatedFile; + + typedef SharedPointer<DirEntry> DirEntryPtr; + typedef QLIST<DirEntryPtr> DirEntries; + typedef QLIST<InfoEntry> InfoEntries; + /// simple list of log entries + typedef QLIST<LogEntry> LogEntries; + /// shared_pointer for LogEntriesMap + typedef SharedPointer<LogEntries> LogEntriesPtr; + + /// map of logentries - key is revision + typedef QMap<long,LogEntry> LogEntriesMap; + /// shared_pointer for LogEntriesMap + typedef SharedPointer<LogEntriesMap> LogEntriesMapPtr; + + typedef SharedPointer<Status> StatusPtr; + typedef QLIST<StatusPtr> StatusEntries; + typedef QLIST<Revision> Revisions; + + /** Range of Revision */ + typedef QPair<Revision,Revision> RevisionRange; + /** list of revision ranges */ + typedef QLIST<RevisionRange> RevisionRanges; + + /// map of property names to values + typedef QMap<QString,QString> PropertiesMap; + /// pair of path, PropertiesMap + typedef QPair<QString, PropertiesMap> PathPropertiesMapEntry; + /// vector of path, Properties pairs + typedef QLIST<PathPropertiesMapEntry> PathPropertiesMapList; + /// shared pointer for properties + typedef SharedPointer<PathPropertiesMapList> PathPropertiesMapListPtr; + + typedef QLIST<Path> Pathes; + + //! Mapper enum for svn_depth_t + /*! + * Until subversion prior 1.5 is supported by this lib we must hide the svn_depth_t enum from interface. + * \since subversion 1.5 / svnqt 1.0 + * \sa svn_depth_t + */ + enum Depth { + DepthUnknown, + DepthExclude, + DepthEmpty, + DepthFiles, + DepthImmediates, + DepthInfinity + }; +} + +#endif diff --git a/src/svnqt/svnstream.cpp b/src/svnqt/svnstream.cpp new file mode 100644 index 0000000..e3b6014 --- /dev/null +++ b/src/svnqt/svnstream.cpp @@ -0,0 +1,263 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "svnqt/svnstream.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/apr.hpp" + +// Subversion api +#include "svn_client.h" + +#include <qbuffer.h> +#include <qdatetime.h> +#include <qfile.h> + +#define MAX_TIME 300 + +namespace svn { + +namespace stream { +class SVNQT_NOEXPORT SvnStream_private +{ +public: + SvnStream_private(){m_Stream=0;m_LastError="";_context=0;cancel_timeout.start();} + ~SvnStream_private(){qDebug("Time elapsed: %i ",cancel_timeout.elapsed());} + + static svn_error_t * stream_write(void*baton,const char*data,apr_size_t*len); + static svn_error_t * stream_read(void*baton,char*data,apr_size_t*len); + + Pool m_Pool; + svn_stream_t * m_Stream; + QString m_LastError; + + svn_client_ctx_t* _context; + QTime cancel_timeout; +}; + +svn_error_t * SvnStream_private::stream_read(void*baton,char*data,apr_size_t*len) +{ + SvnStream*b = (SvnStream*)baton; + svn_client_ctx_t*ctx = b->context(); + + if (ctx&&ctx->cancel_func) { + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + } + + long res = b->isOk()?b->read(data,*len):-1; + + if (res<0) { + *len = 0; + return svn_error_create(SVN_ERR_MALFORMED_FILE,0L,b->lastError().TOUTF8()); + } + *len = res; + return SVN_NO_ERROR; +} + +svn_error_t * SvnStream_private::stream_write(void*baton,const char*data,apr_size_t*len) +{ + SvnStream*b = (SvnStream*)baton; + svn_client_ctx_t*ctx = b->context(); + + if (ctx&&ctx->cancel_func&&b->cancelElapsed()>50) { + qDebug("Check cancel"); + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + b->cancelTimeReset(); + } + + long res = b->isOk()?b->write(data,*len):-1; + if (res<0) { + *len = 0; + return svn_error_create(SVN_ERR_MALFORMED_FILE,0L,b->lastError().TOUTF8()); + } + *len = res; + return SVN_NO_ERROR; +} + +SvnStream::SvnStream(bool read, bool write,svn_client_ctx_t * ctx) +{ + m_Data = new SvnStream_private; + m_Data->m_Stream = svn_stream_create(this,m_Data->m_Pool); + m_Data->_context = ctx; + if (read) { + svn_stream_set_read(m_Data->m_Stream,SvnStream_private::stream_read); + } + if (write) { + svn_stream_set_write(m_Data->m_Stream,SvnStream_private::stream_write); + } +} + +SvnStream::SvnStream() +{ +} + +SvnStream::~SvnStream() +{ + delete m_Data; +} + +int SvnStream::cancelElapsed()const +{ + return m_Data->cancel_timeout.elapsed(); +} + +void SvnStream::cancelTimeReset() +{ + m_Data->cancel_timeout.restart(); +} + +SvnStream::operator svn_stream_t* ()const +{ + return m_Data->m_Stream; +} + +svn_client_ctx_t * SvnStream::context() +{ + return m_Data->_context; +} + +long SvnStream::write(const char*,const unsigned long) +{ + m_Data->m_LastError = "Write not supported with that stream"; + return -1; +} + +long SvnStream::read(char*,const unsigned long ) +{ + m_Data->m_LastError = "Read not supported with that stream"; + return -1; +} + +const QString&SvnStream::lastError()const +{ + return m_Data->m_LastError; +} + +void SvnStream::setError(const QString&aError)const +{ + m_Data->m_LastError = aError; +} + +#if QT_VERSION < 0x040000 +void SvnStream::setError(int ioError)const +{ + switch (ioError) { + case IO_Ok: + setError("Operation was successfull."); + break; + case IO_ReadError: + setError("Could not read from device"); + break; + case IO_WriteError: + setError("Could not write to device"); + break; + case IO_FatalError: + setError("A fatal unrecoverable error occurred."); + break; + case IO_OpenError: + setError("Could not open device or stream."); + break; + case IO_AbortError: + setError("The operation was unexpectedly aborted."); + break; + case IO_TimeOutError: + setError("The operation timed out."); + break; + case IO_UnspecifiedError: + setError("An unspecified error happened on close."); + break; + default: + setError("Unknown error happend."); + break; + } +} +#endif + +class SvnByteStream_private { +public: + SvnByteStream_private(); + virtual ~SvnByteStream_private(){} + + QByteArray m_Content; + QBuffer mBuf; +}; + +#if QT_VERSION < 0x040000 +SvnByteStream_private::SvnByteStream_private() + :mBuf(m_Content) +{ + mBuf.open(IO_WriteOnly); +} +#else +SvnByteStream_private::SvnByteStream_private() + :mBuf(&m_Content, 0) +{ + mBuf.open(QFile::WriteOnly); +} +#endif + +/* ByteStream implementation start */ +SvnByteStream::SvnByteStream(svn_client_ctx_t * ctx) + : SvnStream(false,true,ctx) +{ + m_ByteData = new SvnByteStream_private; + if (!m_ByteData->mBuf.isOpen()) { +#if QT_VERSION < 0x040000 + setError(m_ByteData->mBuf.status()); +#else + setError(m_ByteData->mBuf.errorString()); +#endif + } +} + +SvnByteStream::~SvnByteStream() +{ + delete m_ByteData; +} + +long SvnByteStream::write(const char*aData,const unsigned long max) +{ +#if QT_VERSION < 0x040000 + long i = m_ByteData->mBuf.writeBlock(aData,max); + if (i<0) { + setError(m_ByteData->mBuf.status()); + } +#else + long i = m_ByteData->mBuf.write(aData,max); + if (i<0) { + setError(m_ByteData->mBuf.errorString()); + } +#endif + return i; +} + +QByteArray SvnByteStream::content()const +{ + return m_ByteData->mBuf.buffer(); +} + +bool SvnByteStream::isOk()const +{ + return m_ByteData->mBuf.isOpen(); +} + +/* ByteStream implementation end */ + +} // namespace stream + +} // namespace svn diff --git a/src/svnqt/svnstream.hpp b/src/svnqt/svnstream.hpp new file mode 100644 index 0000000..89276c8 --- /dev/null +++ b/src/svnqt/svnstream.hpp @@ -0,0 +1,164 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SVNSVNSTREAM_HPP +#define SVNSVNSTREAM_HPP + +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +#include <svn_io.h> +struct svn_client_ctx_t; + +namespace svn { + +namespace stream { +class SvnStream_private; + +/** + @author Rajko Albrecht <ral@alwins-world.de> + @short wrapper class around the svn_stream_t structure +*/ +class SVNQT_EXPORT SvnStream{ + friend class SvnStream_private; +public: + //! Constructor + /*! + * Setup a svn_stream_t and holds a required pool. The stream will freed + * when deleting this object. + * \param readit set readable + * \param writeit set writable + * \param ctx a client context for calls to cancel_func inside. you should this only set with functions not using it itself + * like svn_client_cat2: + */ + SvnStream(bool readit, bool writeit, svn_client_ctx_t * ctx = 0); + //! frees all structures and releases memory pool. + virtual ~SvnStream(); + + //! operator returning transparent a svn_stream_t structure + /*! + \return a svn_stream_t structure for use with subversion api. + */ + operator svn_stream_t* ()const; + + //! write operation + /*! + Write data FROM subversion to the class behind. Eg., data comes from + subversion-api and this method has to do something with it (printing on a window, writing to a file) + This implementation always returns -1 (eg, error), must reimplemented for real usage. + \param data the data to written + \param max maximum data to write + \return should return the amount of data real written, in case of error must return -1 + \sa setError(int ioError), setError(const QString&error), read(char*data,const unsigned long max) + */ + virtual long write(const char*data,const unsigned long max); + //! read operation + /*! implements the wrapper for svn_stream_read, eg. data are read FROM class (eg, file, string or whatever) + into subversion-api. This implementation always returns -1 (eg, error), must reimplemented for real usage. + \param data target array where to store the read + \param max maximum byte count to read + \return amount of data read or -1 in case of error + \sa setError(int ioError), setError(const QString&error), write(const char*data,const unsigned long max) + */ + virtual long read(char*data,const unsigned long max); + + //! returns the error set + /*! + \return a human readable message about the reason the last operation failed. + */ + virtual const QString& lastError()const; + //! is that stream usable + /*! + Gives information about if the stream object is usable. May if the file is real open or such. + \return true if stream is usable, false if not. + */ + virtual bool isOk()const = 0; + + svn_client_ctx_t * context(); + +protected: + //! set a human readable errormessage + /*! + This message may printed to the user and will checked if one of the stream-operations failed. So should set from + write and/or read if them will return -1 (for error) + \param error the errormessage assigned. + */ + virtual void setError(const QString&error)const; + //! set the internal error + /*! \param ioError error code from QIODevide::status + */ +#if QT_VERSION < 0x040000 + virtual void setError(int ioError)const; +#endif + +protected: + int cancelElapsed()const; + void cancelTimeReset(); + +private: + SvnStream_private*m_Data; + /* disable default contructor */ + SvnStream(); +}; + +class SvnByteStream_private; + +//! a class let subversion print into a QByteArray +class SVNQT_EXPORT SvnByteStream:public SvnStream +{ +public: + //! constructor + /*! + creates internal buffer + * \param ctx a client context for calls to cancel_func inside. you should this only set with functions not using it itself + * like svn_client_cat2: + */ + SvnByteStream(svn_client_ctx_t * ctx = 0); + //! release internal buffer + virtual ~SvnByteStream(); + //! fill internal buffer with data + /*! + stores the data written into the internal buffer. + \param data data to store + \param max length of data to store + \return data real stored or -1 if error. + */ + virtual long write(const char*data,const unsigned long max); + + //! return the data stored + /*! + \return the internal stored data + */ + QByteArray content()const; + //! checks if the buffer is usable. + /*! + * \return true if data may written, false if not, in that case a errormessage will set. + */ + virtual bool isOk()const; + +private: + SvnByteStream_private*m_ByteData; +}; + +} // namespace stream + +} // namespace svn + +#endif diff --git a/src/svnqt/targets.cpp b/src/svnqt/targets.cpp new file mode 100644 index 0000000..6e2fced --- /dev/null +++ b/src/svnqt/targets.cpp @@ -0,0 +1,170 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// subversion api +#include "svn_types.h" + +// apr api +#include "apr_pools.h" +#include "apr_strings.h" + +// svncpp +#include "svnqt/targets.hpp" +#include "svnqt/path.hpp" +#include "svnqt/pool.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstringlist.h> + +namespace svn +{ + Targets::Targets (const Pathes & targets) + { + m_targets = targets; + } + + Targets::Targets(const QStringList&targets) + { + m_targets.clear(); + for (unsigned int i = 0; i < targets.size();++i) { + if (targets[i].isEmpty()) { + m_targets.push_back(""); + } else { + m_targets.push_back(targets[i]); + } + } + } + + Targets::Targets (const apr_array_header_t * apr_targets) + { + int i; + + m_targets.clear (); + //m_targets.reserve (apr_targets->nelts); + + for (i = 0; i < apr_targets->nelts; i++) + { + const char ** target = + &APR_ARRAY_IDX (apr_targets, i, const char *); + + m_targets.push_back (Path (*target)); + } + } + + Targets::Targets (const Targets & targets) + { + m_targets = targets.targets (); + } + + Targets::Targets (const QString& target) + { + if (!target.isEmpty()) { + m_targets.push_back(target); + } + } + + Targets::Targets (const Path& target) + { + if (!target.cstr().isEmpty()) { + m_targets.push_back(target); + } + } + + Targets::Targets (const char* target) + { + if (target) { + m_targets.push_back(QString::FROMUTF8(target)); + } + } + + Targets::~Targets () + { + } + + apr_array_header_t * + Targets::array (const Pool & pool) const + { + Pathes::const_iterator it; + + apr_pool_t *apr_pool = pool.pool (); + apr_array_header_t *apr_targets = + apr_array_make (apr_pool, + m_targets.size(), + sizeof (const char *)); + + for (it = m_targets.begin (); it != m_targets.end (); it++) + { + QByteArray s = (*it).path().TOUTF8(); + + char * t2 = + apr_pstrndup (apr_pool,s,s.size()); + + (*((const char **) apr_array_push (apr_targets))) = t2; + } + + return apr_targets; + } + + const Pathes & + Targets::targets () const + { + return m_targets; + } + + size_t + Targets::size () const + { + return m_targets.size (); + } + + const Path& Targets::operator [](size_t which)const + { + return m_targets[which]; + } + + const Path + Targets::target (unsigned int which) const + { + if (m_targets.size () > which) + { + return m_targets[which]; + } + else + { + return Path(); + } + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/targets.hpp b/src/svnqt/targets.hpp new file mode 100644 index 0000000..06cef77 --- /dev/null +++ b/src/svnqt/targets.hpp @@ -0,0 +1,168 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_TARGETS_HPP_ +#define _SVNCPP_TARGETS_HPP_ + +#include "svnqt/svnqt_defines.hpp" +#include "svnqt/svnqttypes.hpp" + +#include <qglobal.h> +#if QT_VERSION < 0x040000 +#include <qvaluelist.h> +#else +#include <QtCore> +#endif + +// apr api +#include "apr_tables.h" + +class QStringList; + +namespace svn +{ + // forward declarations + class Pool; + + /** + * Encapsulation for Subversion target arrays handling + */ + class SVNQT_EXPORT Targets + { + public: + /** + * Constructor + * + * @param targets vector of paths + */ + Targets (const Pathes & targets); + + /** + * Constructor + * @param path a single paths + */ + Targets (const Path & targets); + + /** + * Constructor from an APR array containing + * char *. + * + * @param targets APR array header + */ + Targets (const apr_array_header_t * targets); + + /** + * Constructor. Initializes list with just + * one entry + * + * @param target + */ + Targets (const QString& target = QString::null); + /** + * Constructor. Initializes list with just + * one entry + * + * @param target + */ + Targets (const char * target); + /** + * Constructor. Convert stringlist into target list. + * @param targets + */ + Targets(const QStringList&targets); + + /** + * Copy Constructor + * + * @param targets Source + */ + Targets (const Targets & targets); + + /** + * Destructor + */ + virtual ~Targets (); + + /** + * Returns an apr array containing + * char *. + * + * @param pool Pool used for conversion + */ + apr_array_header_t * + array (const Pool & pool) const; + + /** + * Returns a vector of paths + * + * @return vector of paths + */ + const Pathes & + targets() const; + + /** + * @return the number of targets + */ + size_t size () const; + + /** + * operator to return the vector + * + * @return vector with targets + */ + operator const Pathes & () const + { + return m_targets; + } + + const Path& operator [](size_t which)const; + /** + * returns one single target. + * the first in the vector, if no parameter given if there are more + * than one. if there is no target or parameter > then stored pathes returns + * an empty path + * \param which which item we want + * @return single path + */ + const Path + target(unsigned int which = 0) const; + + + private: + Pathes m_targets; + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/testmain.cpp b/src/svnqt/testmain.cpp new file mode 100644 index 0000000..13ae286 --- /dev/null +++ b/src/svnqt/testmain.cpp @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "client.hpp" +#include "repository.hpp" +#include "context.hpp" +#include "datetime.hpp" + +#include <qdatastream.h> + +int main(int,char**) +{ + svn::Client::getobject(0,0); + svn::repository::Repository rep(0L); + svn::ContextP myContext = new svn::Context(); + + QByteArray tout; +#if QT_VERSION < 0x040000 + QDataStream out(tout,IO_WriteOnly); +#endif + svn::Client*m_Svnclient = svn::Client::getobject(0,0); + svn::ContextP m_CurrentContext = new svn::Context(); + m_Svnclient->setContext(m_CurrentContext); + bool gotit = true; + svn::LogEntriesMap m_OldHistory; + + try { + m_Svnclient->log("http://www.alwins-world.de/repos/kdesvn/trunk",svn::Revision::HEAD,20,m_OldHistory,svn::Revision::UNDEFINED,true,false,0); + } catch (svn::ClientException ce) { + gotit = false; + } +#if QT_VERSION < 0x040000 + if (gotit) { + out << m_OldHistory; + svn::LogEntriesMap m_NewHistory; + QDataStream inp(tout,IO_ReadOnly); + inp >> m_NewHistory; + + svn::LogEntriesMap::Iterator it; + for (it=m_NewHistory.begin();it!=m_NewHistory.end();++it) { + qDebug("%lu %s %s",it.key(),it.data().author.ascii(),it.data().message.ascii()); + } + } +#endif + return 1; +} diff --git a/src/svnqt/tests/CMakeLists.txt b/src/svnqt/tests/CMakeLists.txt new file mode 100644 index 0000000..8aef2d5 --- /dev/null +++ b/src/svnqt/tests/CMakeLists.txt @@ -0,0 +1,23 @@ +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +MACRO(BUILD_TEST tname) + SET(${tname}-src ${tname}.cpp) + IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${tname}.h) + SET(${tname}-src ${${tname}-src} ${tname}.h) + ENDIF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${tname}.h) + ADD_EXECUTABLE(${tname} ${${tname}-src}) + TARGET_LINK_LIBRARIES(${tname} ${svnqt-name} ${QT_LIBRARIES}) + ADD_TEST(${tname} ${CMAKE_CURRENT_BINARY_DIR}/${tname}) +ENDMACRO(BUILD_TEST) + +IF (BUILD_TESTS) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/testconfig.h.in + ${CMAKE_CURRENT_BINARY_DIR}/testconfig.h + ) + ADD_TEST(rmrepo "/bin/rm" "-rvf" "${CMAKE_CURRENT_BINARY_DIR}/repo") + ADD_TEST(rmco "/bin/rm" "-rvf" "${CMAKE_CURRENT_BINARY_DIR}/co") + BUILD_TEST(crepo) + BUILD_TEST(lsdir) + BUILD_TEST(ckpath) +ENDIF(BUILD_TESTS) diff --git a/src/svnqt/tests/ckpath.cpp b/src/svnqt/tests/ckpath.cpp new file mode 100644 index 0000000..ca4fe3e --- /dev/null +++ b/src/svnqt/tests/ckpath.cpp @@ -0,0 +1,24 @@ +#include "src/svnqt/path.hpp" +#include <iostream> + +int main(int,char**) +{ + svn::Path pa("/test/foo/bar/"); + if (pa.path()!=QString("/test/foo/bar")) { + std::cout << "No cleanup of components" << std::endl; + return -1; + } + pa.removeLast(); + if (pa.path()!=QString("/test/foo")) { + std::cout<<"removeLast didn't work." << std::endl; + return -1; + } + unsigned j = 0; + while (pa.length()>0) { + std::cout << pa.path() << std::endl; + pa.removeLast(); + ++j; + } + return 0; +} + diff --git a/src/svnqt/tests/crepo.cpp b/src/svnqt/tests/crepo.cpp new file mode 100644 index 0000000..604e4e9 --- /dev/null +++ b/src/svnqt/tests/crepo.cpp @@ -0,0 +1,63 @@ +#include "src/svnqt/client.hpp" +#include "src/svnqt/tests/testconfig.h" +#include "src/svnqt/repository.hpp" +#include "src/svnqt/repositorylistener.hpp" +#include "src/svnqt/targets.hpp" + +#include "testlistener.h" + +#include <iostream> +#include <unistd.h> +#include <qstringlist.h> + +class Listener:public svn::repository::RepositoryListener +{ + public: + Listener(){} + virtual ~Listener(){} + virtual void sendWarning(const QString&msg) + { + std::cout << msg << std::endl; + } + virtual void sendError(const QString&msg) + { + std::cout << msg << std::endl; + } + virtual bool isCanceld(){return false;} +}; + +int main(int,char**) +{ + QString p = TESTREPOPATH; + Listener ls; + svn::repository::Repository rp(&ls); + try { + rp.CreateOpen(p,"fsfs"); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + + svn::ContextP m_CurrentContext; + svn::Client* m_Svnclient; + m_Svnclient=svn::Client::getobject(0,0); + TestListener tl; + m_CurrentContext = new svn::Context(); + m_CurrentContext->setListener(&tl); + p = "file://"+p; + + m_Svnclient->setContext(m_CurrentContext); + QStringList s; s.append(p+"/trunk"); s.append(p+"/branches"); s.append(p+"/tags"); + + try { + m_Svnclient->mkdir(svn::Targets(s),"Test mkdir"); + m_Svnclient->checkout(p,TESTCOPATH,svn::Revision::HEAD,svn::Revision::HEAD,svn::DepthInfinity,false); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + + return 0; +} diff --git a/src/svnqt/tests/lsdir.cpp b/src/svnqt/tests/lsdir.cpp new file mode 100644 index 0000000..c458f31 --- /dev/null +++ b/src/svnqt/tests/lsdir.cpp @@ -0,0 +1,78 @@ + +#include "src/svnqt/client.hpp" +#include "src/svnqt/tests/testconfig.h" +#include "src/svnqt/status.hpp" +#include "src/svnqt/svnqttypes.hpp" +#include <iostream> + +int main(int,char**) +{ + svn::ContextP m_CurrentContext; + svn::Client* m_Svnclient; + m_Svnclient=svn::Client::getobject(0,0); + m_CurrentContext = new svn::Context(); + + m_Svnclient->setContext(m_CurrentContext); + svn::DirEntries dlist; + + QString p = QString("file://%1").arg(TESTREPOPATH); + QString l = QString("%1").arg(TESTCOPATH); + + try { + dlist = m_Svnclient->list(svn::Path(p),svn::Revision::HEAD,svn::Revision::HEAD,svn::DepthInfinity,true); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + std::cout << "List 1 "<<dlist.size()<<std::endl; + for (unsigned int i=0; i < dlist.size();++i) { + QDateTime dt = svn::DateTime(dlist[i]->time()); + std::cout << dlist[i]->name() << " " + << dlist[i]->lastAuthor() << " " + << dlist[i]->size() << " " + << dt.toTime_t() << std::endl; + } + try { + dlist = m_Svnclient->list(svn::Path(p),svn::Revision::HEAD,svn::Revision::HEAD,svn::DepthImmediates,false); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + std::cout << "================"<<std::endl; + std::cout << "List 2 "<<dlist.size()<<std::endl; + for (unsigned int i=0; i < dlist.size();++i) { + QDateTime dt = svn::DateTime(dlist[i]->time()); + std::cout << dlist[i]->name() << " " + << dlist[i]->lastAuthor() << " " + << dlist[i]->size() << " " + << dt.toTime_t() << std::endl; + } + std::cout << "================"<<std::endl; + svn::StatusEntries slist; + try { + slist = m_Svnclient->status(svn::Path(p),svn::DepthInfinity,true,true,true,svn::Revision::HEAD,true,false); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + for (unsigned int i=0; i < slist.size();++i) { + std::cout << slist[i]->path()<< std::endl; + } + std::cout << "================"<<std::endl; + std::cout << "Second status:"<<std::endl; + try { + slist = m_Svnclient->status(svn::Path(l),svn::DepthInfinity,true,true,true,svn::Revision::WORKING,true,false); + } catch (svn::ClientException e) { + QString ex = e.msg(); + std::cout << ex.TOUTF8() << std::endl; + return -1; + } + for (unsigned int i=0; i < slist.size();++i) { + std::cout << slist[i]->path()<< std::endl; + } + + return 0; +} diff --git a/src/svnqt/tests/testconfig.h.in b/src/svnqt/tests/testconfig.h.in new file mode 100644 index 0000000..5ffff3e --- /dev/null +++ b/src/svnqt/tests/testconfig.h.in @@ -0,0 +1,7 @@ +#ifndef __TEST_CONFIG_H +#define __TEST_CONFIG_H + +#define TESTREPOPATH "@CMAKE_CURRENT_BINARY_DIR@/repo" +#define TESTCOPATH "@CMAKE_CURRENT_BINARY_DIR@/co" + +#endif diff --git a/src/svnqt/tests/testlistener.h b/src/svnqt/tests/testlistener.h new file mode 100644 index 0000000..0c38a43 --- /dev/null +++ b/src/svnqt/tests/testlistener.h @@ -0,0 +1,37 @@ +#ifndef _TESTLISTENER_ +#define _TESTLISTENER_ + +#include "src/svnqt/context_listener.hpp" + +class TestListener:public svn::ContextListener +{ + public: + TestListener(){} + virtual ~TestListener(){} + + virtual void contextProgress(long long int current, long long int max){}; + virtual bool contextSslClientCertPwPrompt (QString &,const QString &, bool &){return false;} + virtual bool contextLoadSslClientCertPw(QString&,const QString&){return false;} + virtual bool contextSslClientCertPrompt (QString &){return false;} + virtual svn::ContextListener::SslServerTrustAnswer + contextSslServerTrustPrompt (const SslServerTrustData &, + apr_uint32_t & ){return svn::ContextListener::SslServerTrustAnswer();} + virtual bool contextGetLogMessage (QString &,const svn::CommitItemList&){return false;} + virtual bool contextCancel(){return false;} + virtual void contextNotify (const svn_wc_notify_t *){} + virtual void contextNotify (const char *,svn_wc_notify_action_t, + svn_node_kind_t, + const char *, + svn_wc_notify_state_t, + svn_wc_notify_state_t, + svn_revnum_t){} + virtual bool contextGetSavedLogin (const QString & realm,QString & username,QString & password){return false;} + virtual bool contextGetCachedLogin (const QString & realm,QString & username,QString & password){return false;} + virtual bool contextGetLogin (const QString & realm, + QString & username, + QString & password, + bool & maySave){maySave=false;return false;} + +}; + +#endif diff --git a/src/svnqt/url.cpp b/src/svnqt/url.cpp new file mode 100644 index 0000000..185f582 --- /dev/null +++ b/src/svnqt/url.cpp @@ -0,0 +1,209 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ +#if defined( _MSC_VER) && _MSC_VER <= 1200 +#pragma warning( disable: 4786 )// debug symbol truncated +#endif + + +// svncpp +#include "pool.hpp" +#include "url.hpp" + +#include <qglobal.h> +#if QT_VERSION < 0x040000 +#include <qvaluelist.h> +#else +#include <QtCore> +#endif + +// subversion api +#include "svn_ra.h" + +namespace svn +{ + static const char * + VALID_SCHEMAS [] = + { + "http","https","file", + "svn","svn+ssh","svn+http","svn+https","svn+file", + "ksvn","ksvn+ssh","ksvn+http","ksvn+https","ksvn+file","ksvn", + 0 + }; + + static bool mSchemasInitialized = false; +#if QT_VERSION < 0x040000 + QValueList<QString> mSchemas; +#else + QList<QString> mSchemas; +#endif + + Url::Url () {} + + Url::~Url () {} + + bool Url::isLocal(const QString& url) + { +#if QT_VERSION < 0x040000 + bool cs = false; +#else + Qt::CaseSensitivity cs=Qt::CaseInsensitive; +#endif + if ( + url.startsWith("file://",cs) || + url.startsWith("/") || + url.startsWith("svn+file://",cs) || + url.startsWith("ksvn+file://",cs) ) + { + return true; + } + return false; + } + + bool Url::isValid (const QString& url) + { + QString urlTest(url); + unsigned int index = 0; + while (VALID_SCHEMAS[index]!=0) + { + QString schema = QString::FROMUTF8(VALID_SCHEMAS[index]); + QString urlComp = urlTest.mid(0, schema.length()); + + if (schema == urlComp) + { + return true; + } + ++index; + } + + return false; + } + + QString + Url::transformProtokoll(const QString&prot) + { +#if QT_VERSION < 0x040000 + QString _prot = prot.lower(); +#else + QString _prot = prot.toLower(); +#endif + if (QString::compare(_prot,"svn+http")==0|| + QString::compare(_prot,"ksvn+http")==0) { + return QString("http"); + } else if (QString::compare(_prot,"svn+https")==0|| + QString::compare(_prot,"ksvn+https")==0) { + return QString("https"); + }else if (QString::compare(_prot,"svn+file")==0|| + QString::compare(_prot,"ksvn+file")==0) { + return QString("file"); + } else if (QString::compare(_prot,"ksvn+ssh")==0) { + return QString("svn+ssh"); + } else if (QString::compare(_prot,"ksvn")==0) { + return QString("svn"); + } + return _prot; + } + + + /** + * the implementation of the function that pull the supported + * url schemas out of the ra layer it rather dirty now since + * we are lacking a higher level of abstraction + */ +#if QT_VERSION < 0x040000 + QValueList<QString> +#else + QList<QString> +#endif + Url::supportedSchemas () + { + if (mSchemasInitialized) + return mSchemas; + + mSchemasInitialized = true; + Pool pool; + void * ra_baton; + + svn_error_t * error = + svn_ra_init_ra_libs (&ra_baton, pool); + if (error) + return mSchemas; + + svn_stringbuf_t *descr; + error = + svn_ra_print_ra_libraries (&descr, ra_baton, pool); + if (error) + return mSchemas; + + // schemas are in the following form: + // <schema>:<whitespace><description>\n... + // find the f�st : + QString descriptions (descr->data); + int pos=0; + const int not_found = -1; + do + { + const QString tokenStart ("handles '"); + const QString tokenEnd ("' schem"); +#if QT_VERSION < 0x040000 + pos = descriptions.find (tokenStart, pos); +#else + pos = descriptions.indexOf( tokenStart, pos ); +#endif + if (pos == not_found) + break; + + pos += tokenStart.length (); + +#if QT_VERSION < 0x040000 + int posEnd = descriptions.find (tokenEnd, pos); +#else + int posEnd = descriptions.indexOf( tokenEnd, pos ); +#endif + if (posEnd == not_found) + break; + + // found + QString schema (descriptions.mid(pos, posEnd-pos) + ":"); + mSchemas.push_back (schema); + + // forward to the next newline + pos = posEnd + tokenEnd.length (); + } + while (pos != not_found); + + return mSchemas; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/url.hpp b/src/svnqt/url.hpp new file mode 100644 index 0000000..795d4c8 --- /dev/null +++ b/src/svnqt/url.hpp @@ -0,0 +1,104 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_URL_H_ +#define _SVNCPP_URL_H_ + +#include "svnqt/svnqt_defines.hpp" + +// qt +#include <qglobal.h> +#if QT_VERSION < 0x040000 + +#include <qstring.h> +#include <qvaluelist.h> + +#else + +#include <QtCore> + +#endif + + +namespace svn +{ + class SVNQT_EXPORT Url + { + public: + /** Constructor */ + Url (); + + /** Destructor */ + virtual ~Url (); + + /** + * Checks if @a url is valid + * + * Example of a valid URL: + * http://svn.collab.net/repos/svn + * Example of an invalid URL: + * /home/foo/bar + */ + static bool + isValid (const QString& url); + + /** + * Checks if @a url points to a local filesystem. + * + * @return true if url is accessed local without network. + */ + static bool + isLocal(const QString& url); + + static QString + transformProtokoll(const QString&); + + /** + * returns a vector with url schemas that are + * supported by svn + * + * @return vector with entries like "file:", "http:" + */ +#if QT_VERSION < 0x040000 + static QValueList<QString> +#else + static QList<QString> +#endif + supportedSchemas (); + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ + diff --git a/src/svnqt/version_check.cpp b/src/svnqt/version_check.cpp new file mode 100644 index 0000000..02f6b10 --- /dev/null +++ b/src/svnqt/version_check.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "version_check.hpp" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <svn_version.h> +#include <svn_client.h> + +#include <qstring.h> + +namespace svn { + static const svn_version_t Linkedtag = { + SVN_VER_MAJOR, + SVN_VER_MINOR, + SVN_VER_PATCH, + SVN_VER_NUMTAG + }; + + static QString curr_version_string; + + bool Version::client_version_compatible() + { + return svn_ver_compatible(svn_client_version(),&Linkedtag); + } + + const QString Version::linked_version() + { + return QString( SVN_VERSION ); + } + + const QString Version::running_version() + { + if (curr_version_string.length()==0) { + curr_version_string = + QString("%1.%2.%3.%4").arg(svn_client_version()->major).arg(svn_client_version()->minor) + .arg(svn_client_version()->patch).arg(svn_client_version()->tag); + } + return curr_version_string; + } + + int Version::version_major() + { + return svn_client_version()->major; + } + + int Version::version_minor() + { + return svn_client_version()->minor; + } +} diff --git a/src/svnqt/version_check.hpp b/src/svnqt/version_check.hpp new file mode 100644 index 0000000..2398645 --- /dev/null +++ b/src/svnqt/version_check.hpp @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef __VERSION_CHECK_HPP +#define __VERSION_CHECK_HPP + +#include "svnqt/svnqt_defines.hpp" + +class QString; + +namespace svn { + class SVNQT_EXPORT Version { + + public: + Version(){} + ~Version(){} + + static bool client_version_compatible(); + static const QString linked_version(); + static const QString running_version(); + + static int version_major(); + static int version_minor(); + }; +} + +#endif diff --git a/src/svnqt/wc.cpp b/src/svnqt/wc.cpp new file mode 100644 index 0000000..bcfe139 --- /dev/null +++ b/src/svnqt/wc.cpp @@ -0,0 +1,129 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +// subversion api +#include "svn_wc.h" + +// svncpp +#include "exception.hpp" +#include "path.hpp" +#include "pool.hpp" +#include "wc.hpp" + +namespace svn +{ + const char * Wc::ADM_DIR_NAME = SVN_WC_ADM_DIR_NAME; + + bool + Wc::checkWc (const QString& dir) + { + Pool pool; + Path path (dir); + int wc; + + svn_error_t * error = svn_wc_check_wc ( + path.path().TOUTF8(), + &wc, pool); + + if ((error != NULL) || (wc == 0)) + { + return false; + } + + return true; + } + + void + Wc::ensureAdm (const QString& dir, const QString& uuid, + const QString& url, const Revision & revision) throw (ClientException) + { + Pool pool; + Path dirPath (dir); + Path urlPath (url); + + svn_error_t * error = + svn_wc_ensure_adm ( + dirPath.path().TOUTF8(), // path + uuid.TOUTF8(), // UUID + urlPath.path().TOUTF8(), // url + revision.revnum (), // revision + pool); + if(error != NULL) + throw ClientException (error); + } + + const svn_wc_entry_t *Wc::getEntry( const QString &path ) throw ( ClientException ) + { + Pool pool; + Path itemPath(path); + svn_error_t * error = 0; + svn_wc_adm_access_t *adm_access; + const svn_wc_entry_t *entry; + error = svn_wc_adm_probe_open2(&adm_access,0,itemPath.path().TOUTF8(),FALSE,0,pool); + if (error!=0) { + throw ClientException(error); + } + error = svn_wc_entry(&entry,itemPath.path().TOUTF8(),adm_access,FALSE,pool); + if (error!=0) { + throw ClientException(error); + } + error = svn_wc_adm_close(adm_access); + if (error!=0) { + throw ClientException(error); + } + return entry; + } + + QString Wc::getUrl(const QString&path) throw (ClientException) + { + QString result = ""; + const svn_wc_entry_t *entry; + entry = getEntry( path ); + result = entry?QString::FROMUTF8(entry->url):""; + + return result; + } + + QString Wc::getRepos(const QString&path) throw (ClientException) + { + QString result = ""; + const svn_wc_entry_t *entry; + entry = getEntry( path ); + result = entry ? QString::FROMUTF8(entry->repos) : QString::fromLatin1(""); + + return result; + } +} + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/svnqt/wc.hpp b/src/svnqt/wc.hpp new file mode 100644 index 0000000..b8769f8 --- /dev/null +++ b/src/svnqt/wc.hpp @@ -0,0 +1,96 @@ +/* + * Port for usage with qt-framework and development for kdesvn + * (C) 2005-2007 by Rajko Albrecht + * http://kdesvn.alwins-world.de + */ +/* + * ==================================================================== + * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library (in the file LGPL.txt); if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, + * Fifth Floor, Boston, MA 02110-1301 USA + * + * This software consists of voluntary contributions made by many + * individuals. For exact contribution history, see the revision + * history and logs, available at http://rapidsvn.tigris.org/. + * ==================================================================== + */ + +#ifndef _SVNCPP_WC_HPP_ +#define _SVNCPP_WC_HPP_ + +// Ignore MSVC 7, 2005 & 2008 compiler warning: C++ exception specification +#if defined (_MSC_VER) && _MSC_VER > 1200 && _MSC_VER <= 1550 +#pragma warning (disable: 4290) +#endif + +// svncpp +#include "svnqt/exception.hpp" +#include "svnqt/revision.hpp" +#include "svnqt/svnqt_defines.hpp" + +#include <qstring.h> + +namespace svn +{ + /** + * Class that deals with a working copy + */ + class SVNQT_EXPORT Wc + { + public: + /** + * check if Path is a valid working directory + * + * @param dir path to a directory + * @return true=valid working copy + */ + static bool + checkWc (const QString& dir); + + /** + * ensure that an administrative area exists for @a dir, so that @a dir + * is a working copy subdir based on @a url at @a revision. + * + * @param dir path to a directory + * @param uuid + * @param url corresponding url + * @param revision expected working copy revision + */ + static void + ensureAdm (const QString& dir, const QString& uuid, + const QString& url, const Revision & revision) throw (ClientException); + + /** + * retrieve the url of a given working copy item + * @param path the working copy item to check + * @return the repository url of @a path + */ + static QString getUrl(const QString&path) throw (ClientException); + static QString getRepos(const QString&path) throw (ClientException); + static const char * ADM_DIR_NAME; + + private: + static const svn_wc_entry_t *getEntry( const QString &path ) throw ( ClientException ); + + }; +} + +#endif +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "../../rapidsvn-dev.el") + * end: + */ diff --git a/src/urldlg.cpp b/src/urldlg.cpp new file mode 100644 index 0000000..49293f2 --- /dev/null +++ b/src/urldlg.cpp @@ -0,0 +1,146 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "urldlg.h" +#include <kcombobox.h> +#include <kurlrequester.h> +#include <qlayout.h> +#include <kconfig.h> +#include <klocale.h> +#include <kglobal.h> +#include <klineedit.h> +#include <kurl.h> +#include <kdebug.h> + +#include <qlabel.h> + +UrlDlg::UrlDlg(QWidget *parent, const char *name) + : KDialogBase(Plain, QString::null, Ok|Cancel|User1, Ok, parent, name, + true,true, KStdGuiItem::clear()) +{ + init_dlg(); +} + + +UrlDlg::~UrlDlg() +{ +} + + +/*! + \fn UrlDlg::init_dlg + */ +void UrlDlg::init_dlg() +{ + QVBoxLayout * topLayout = new QVBoxLayout( plainPage(), 0, spacingHint()); + QLabel * label = new QLabel(i18n("Open repository or working copy") , plainPage()); + topLayout->addWidget(label); + + KHistoryCombo * combo = new KHistoryCombo(0,"history_combo"); + combo->setDuplicatesEnabled(false); + KConfig *kc = KGlobal::config(); + KConfigGroupSaver ks( kc, QString::fromLatin1("Open-repository settings") ); + int max = kc->readNumEntry( QString::fromLatin1("Maximum history"), 15 ); + combo->setMaxCount( max ); + QStringList list = kc->readListEntry( QString::fromLatin1("History") ); + combo->setHistoryItems(list); + combo->setMinimumWidth(100); + combo->adjustSize(); + if (combo->width()>300) { + combo->resize(300,combo->height()); + } + + urlRequester_ = new KURLRequester(combo, plainPage(), "urlRequester"); + topLayout->addWidget( urlRequester_ ); + urlRequester_->setFocus(); + KFile::Mode mode = static_cast<KFile::Mode>(KFile::ExistingOnly|KFile::Directory); + urlRequester_->setMode(mode); + connect(urlRequester_->comboBox(),SIGNAL(textChanged(const QString&)),SLOT(slotTextChanged(const QString&))); + enableButtonOK( false ); + enableButton( KDialogBase::User1, false ); + connect( this, SIGNAL(user1Clicked()), SLOT(slotClear())); + urlRequester_->adjustSize(); + resize(QSize(400,sizeHint().height())); +} + +/*! + \fn UrlDlg::accept() + */ +void UrlDlg::accept() +{ + KHistoryCombo *combo = static_cast<KHistoryCombo*>(urlRequester_->comboBox()); + if (combo) { + combo->addToHistory(urlRequester_->url()); + KConfig *kc = KGlobal::config(); + KConfigGroupSaver ks(kc, QString::fromLatin1("Open-repository settings")); + kc->writeEntry(QString::fromLatin1("History"), combo->historyItems()); + kc->sync(); + } + KDialogBase::accept(); +} + + +/*! + \fn UrlDlg::slotTextChanged(const QString&) + */ +void UrlDlg::slotTextChanged(const QString&text) +{ + bool state = !text.stripWhiteSpace().isEmpty(); + enableButtonOK( state ); + enableButton( KDialogBase::User1, state ); +} + + +/*! + \fn UrlDlg::slotClear() + */ +void UrlDlg::slotClear() +{ + urlRequester_->clear(); +} + + +/*! + \fn UrlDlg::selectedURL() + */ +KURL UrlDlg::selectedURL() +{ + if ( result() == QDialog::Accepted ) { + KURL uri = urlRequester_->url(); + return uri; + //return KURL::fromPathOrURL( urlRequester_->url() ); + } else { + return KURL(); + } +} + + +/*! + \fn UrlDlg::getURL(QWidget*parent) + */ +KURL UrlDlg::getURL(QWidget*parent) +{ + UrlDlg dlg(parent); + dlg.setCaption(i18n("Open")); + dlg.exec(); + const KURL& url = dlg.selectedURL(); + return url; +} + +#include "urldlg.moc" diff --git a/src/urldlg.h b/src/urldlg.h new file mode 100644 index 0000000..137c47f --- /dev/null +++ b/src/urldlg.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * ral@alwins-world.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef URLDLG_H +#define URLDLG_H + +#include <kdialogbase.h> +#include <kurl.h> + +class KURLRequester; + +/** +@author Rajko Albrecht +*/ +class UrlDlg : public KDialogBase +{ +Q_OBJECT +public: + UrlDlg(QWidget *parent = 0, const char *name = 0); + ~UrlDlg(); + KURL selectedURL(); + static KURL getURL(QWidget*parent=0); +protected: + virtual void init_dlg(); + KURLRequester*urlRequester_; +protected slots: + virtual void accept(); + virtual void slotTextChanged(const QString&); + virtual void slotClear(); +}; + +#endif |