summaryrefslogtreecommitdiffstats
path: root/src/svnfrontend
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-15 17:32:48 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-15 17:32:48 +0000
commite2f541c98dfa4081fa3ab3d28f08ea2309281884 (patch)
treecb721a55bc88753ddeb9754dc98ef45e2850ce30 /src/svnfrontend
downloadtdesvn-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/svnfrontend')
-rw-r--r--src/svnfrontend/CMakeLists.txt86
-rw-r--r--src/svnfrontend/blamedisplay.ui108
-rw-r--r--src/svnfrontend/blamedisplay_impl.cpp490
-rw-r--r--src/svnfrontend/blamedisplay_impl.h65
-rw-r--r--src/svnfrontend/cacheentry.h581
-rw-r--r--src/svnfrontend/ccontextlistener.cpp353
-rw-r--r--src/svnfrontend/ccontextlistener.h96
-rw-r--r--src/svnfrontend/commandexec.cpp650
-rw-r--r--src/svnfrontend/commandexec.h87
-rw-r--r--src/svnfrontend/copymoveview.ui102
-rw-r--r--src/svnfrontend/copymoveview_impl.cpp102
-rw-r--r--src/svnfrontend/copymoveview_impl.h54
-rw-r--r--src/svnfrontend/createrepo_dlg.ui207
-rw-r--r--src/svnfrontend/createrepo_impl.cpp126
-rw-r--r--src/svnfrontend/createrepo_impl.h46
-rw-r--r--src/svnfrontend/dummydisplay.cpp55
-rw-r--r--src/svnfrontend/dummydisplay.h40
-rw-r--r--src/svnfrontend/dumprepo_dlg.ui200
-rw-r--r--src/svnfrontend/dumprepo_impl.cpp112
-rw-r--r--src/svnfrontend/dumprepo_impl.h40
-rw-r--r--src/svnfrontend/editproperty_impl.cpp209
-rw-r--r--src/svnfrontend/editproperty_impl.h54
-rw-r--r--src/svnfrontend/editpropsdlg.ui244
-rw-r--r--src/svnfrontend/filelistviewitem.cpp322
-rw-r--r--src/svnfrontend/filelistviewitem.h88
-rw-r--r--src/svnfrontend/fillcachethread.cpp123
-rw-r--r--src/svnfrontend/fillcachethread.h54
-rw-r--r--src/svnfrontend/frontendtypes.h11
-rw-r--r--src/svnfrontend/fronthelpers/checkoutinfo.ui223
-rw-r--r--src/svnfrontend/fronthelpers/checkoutinfo_impl.cpp211
-rw-r--r--src/svnfrontend/fronthelpers/checkoutinfo_impl.h56
-rw-r--r--src/svnfrontend/fronthelpers/cursorstack.h56
-rw-r--r--src/svnfrontend/fronthelpers/propertyitem.cpp56
-rw-r--r--src/svnfrontend/fronthelpers/propertyitem.h49
-rw-r--r--src/svnfrontend/fronthelpers/propertylist.cpp166
-rw-r--r--src/svnfrontend/fronthelpers/propertylist.h57
-rw-r--r--src/svnfrontend/fronthelpers/rangeinput.ui285
-rw-r--r--src/svnfrontend/fronthelpers/rangeinput_impl.cpp193
-rw-r--r--src/svnfrontend/fronthelpers/rangeinput_impl.h58
-rw-r--r--src/svnfrontend/fronthelpers/revisionbutton.ui55
-rw-r--r--src/svnfrontend/fronthelpers/revisionbuttonimpl.cpp75
-rw-r--r--src/svnfrontend/fronthelpers/revisionbuttonimpl.h51
-rw-r--r--src/svnfrontend/fronthelpers/widgetblockstack.cpp38
-rw-r--r--src/svnfrontend/fronthelpers/widgetblockstack.h33
-rw-r--r--src/svnfrontend/graphtree/drawparams.cpp708
-rw-r--r--src/svnfrontend/graphtree/drawparams.h200
-rw-r--r--src/svnfrontend/graphtree/elogentry.cpp76
-rw-r--r--src/svnfrontend/graphtree/elogentry.h37
-rw-r--r--src/svnfrontend/graphtree/graphtree_defines.h31
-rw-r--r--src/svnfrontend/graphtree/graphtreelabel.cpp220
-rw-r--r--src/svnfrontend/graphtree/graphtreelabel.h89
-rw-r--r--src/svnfrontend/graphtree/pannerview.cpp101
-rw-r--r--src/svnfrontend/graphtree/pannerview.h53
-rw-r--r--src/svnfrontend/graphtree/revgraphview.cpp950
-rw-r--r--src/svnfrontend/graphtree/revgraphview.h151
-rw-r--r--src/svnfrontend/graphtree/revisiontree.cpp544
-rw-r--r--src/svnfrontend/graphtree/revisiontree.h75
-rw-r--r--src/svnfrontend/graphtree/revtreewidget.cpp115
-rw-r--r--src/svnfrontend/graphtree/revtreewidget.h74
-rw-r--r--src/svnfrontend/hotcopydlg.ui94
-rw-r--r--src/svnfrontend/hotcopydlg_impl.cpp60
-rw-r--r--src/svnfrontend/hotcopydlg_impl.h42
-rw-r--r--src/svnfrontend/importdir_logmsg.cpp87
-rw-r--r--src/svnfrontend/importdir_logmsg.h48
-rw-r--r--src/svnfrontend/itemdisplay.cpp119
-rw-r--r--src/svnfrontend/itemdisplay.h68
-rw-r--r--src/svnfrontend/kdesvnfilelist.cpp3160
-rw-r--r--src/svnfrontend/kdesvnfilelist.h243
-rw-r--r--src/svnfrontend/keystatus.cpp39
-rw-r--r--src/svnfrontend/keystatus.h33
-rw-r--r--src/svnfrontend/loaddmpdlg.ui183
-rw-r--r--src/svnfrontend/loaddmpdlg_impl.cpp106
-rw-r--r--src/svnfrontend/loaddmpdlg_impl.h40
-rw-r--r--src/svnfrontend/merge_dlg.ui213
-rw-r--r--src/svnfrontend/mergedlg_impl.cpp213
-rw-r--r--src/svnfrontend/mergedlg_impl.h54
-rw-r--r--src/svnfrontend/modifiedthread.cpp79
-rw-r--r--src/svnfrontend/modifiedthread.h56
-rw-r--r--src/svnfrontend/opencontextmenu.cpp83
-rw-r--r--src/svnfrontend/opencontextmenu.h50
-rw-r--r--src/svnfrontend/propertiesdlg.cpp293
-rw-r--r--src/svnfrontend/propertiesdlg.h97
-rw-r--r--src/svnfrontend/simple_logcb.h51
-rw-r--r--src/svnfrontend/stopdlg.cpp216
-rw-r--r--src/svnfrontend/stopdlg.h105
-rw-r--r--src/svnfrontend/svnactions.cpp2891
-rw-r--r--src/svnfrontend/svnactions.h254
-rw-r--r--src/svnfrontend/svnfiletip.cpp308
-rw-r--r--src/svnfrontend/svnfiletip.h97
-rw-r--r--src/svnfrontend/svnitem.cpp535
-rw-r--r--src/svnfrontend/svnitem.h111
-rw-r--r--src/svnfrontend/svnlogdlg.ui479
-rw-r--r--src/svnfrontend/svnlogdlgimp.cpp661
-rw-r--r--src/svnfrontend/svnlogdlgimp.h89
-rw-r--r--src/svnfrontend/tcontextlistener.cpp319
-rw-r--r--src/svnfrontend/tcontextlistener.h72
-rw-r--r--src/svnfrontend/threadcontextlistenerdata.cpp30
-rw-r--r--src/svnfrontend/threadcontextlistenerdata.h85
98 files changed, 21554 insertions, 0 deletions
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&amp;)</signal>
+ <receiver>BlameDisplay</receiver>
+ <slot>slotContextMenuRequested(KListView*,QListViewItem*,const QPoint&amp;)</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&amp;)</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>&lt;p align="right"&gt;Rename&lt;/p&gt;</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 (&lt;tt&gt;/trunk&lt;/tt&gt;,&lt;tt&gt;/branches&lt;/tt&gt; and &lt;tt&gt;/tags&lt;/tt&gt;) 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&amp;)</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&amp;)</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&currentName()const{return m_currentName;}
+ const QString&currentValue()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&amp;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&amp;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&current,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&amp;,int)</signal>
+ <receiver>LogDialog</receiver>
+ <slot>slotItemClicked(int,QListViewItem*,const QPoint&amp;,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&amp;,int)</signal>
+ <receiver>LogDialog</receiver>
+ <slot>slotSingleContext(QListViewItem*,const QPoint&amp;,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 &amp;,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 &amp;, 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