1 /* This file is part of the KDE project
2 Copyright (C) 2000 David Faure <faure@kde.org>
3 Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License version 2 or at your option version 3 as published by
8 the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
23 #include "bookmarkmodel.h"
25 #include "bookmarkinfo.h"
26 #include "actionsimpl.h"
27 #include "exporters.h"
30 #include "kebsearchline.h"
31 #include "bookmarklistview.h"
35 #include <QtGui/QClipboard>
36 #include <QtGui/QSplitter>
37 #include <QtGui/QLayout>
38 #include <QtGui/QLabel>
41 #include <kactioncollection.h>
42 #include <ktoggleaction.h>
43 #include <kapplication.h>
44 #include <kbookmark.h>
45 #include <kbookmarkmanager.h>
47 #include <kedittoolbar.h>
48 #include <kfiledialog.h>
49 #include <klineedit.h>
51 #include <kmessagebox.h>
52 #include <kstandardaction.h>
55 #include <QtCore/QBool>
59 CmdHistory
* CmdHistory::s_self
= 0;
61 CmdHistory::CmdHistory(KActionCollection
*collection
)
62 : m_commandHistory(collection
) {
63 connect(&m_commandHistory
, SIGNAL( commandExecuted(K3Command
*) ),
64 SLOT( slotCommandExecuted(K3Command
*) ));
66 s_self
= this; // this is hacky
69 CmdHistory
* CmdHistory::self() {
74 void CmdHistory::slotCommandExecuted(K3Command
*k
) {
75 KEBApp::self()->notifyCommandExecuted();
77 IKEBCommand
* cmd
= dynamic_cast<IKEBCommand
*>(k
);
80 KBookmark bk
= CurrentMgr::bookmarkAt(cmd
->affectedBookmarks());
81 Q_ASSERT(bk
.isGroup());
82 CurrentMgr::self()->notifyManagers(bk
.toGroup());
85 void CmdHistory::notifyDocSaved() {
86 m_commandHistory
.documentSaved();
89 void CmdHistory::didCommand(K3Command
*cmd
) {
92 m_commandHistory
.addCommand(cmd
, false);
93 CmdHistory::slotCommandExecuted(cmd
);
96 void CmdHistory::addCommand(K3Command
*cmd
) {
99 m_commandHistory
.addCommand(cmd
);
102 void CmdHistory::addInFlightCommand(K3Command
*cmd
)
106 m_commandHistory
.addCommand(cmd
, false);
109 void CmdHistory::clearHistory() {
110 m_commandHistory
.clear();
113 /* -------------------------- */
115 CurrentMgr
*CurrentMgr::s_mgr
= 0;
117 CurrentMgr::CurrentMgr()
119 m_mgr(0), m_model(0), ignorenext(0)
123 CurrentMgr::~CurrentMgr()
131 KBookmarkGroup
CurrentMgr::root()
133 return mgr()->root();
136 KBookmark
CurrentMgr::bookmarkAt(const QString
&a
)
138 return self()->mgr()->findByAddress(a
);
141 bool CurrentMgr::managerSave() { return mgr()->save(); }
142 void CurrentMgr::saveAs(const QString
&fileName
) { mgr()->saveAs(fileName
); }
143 void CurrentMgr::setUpdate(bool update
) { mgr()->setUpdate(update
); }
144 QString
CurrentMgr::path() const { return mgr()->path(); }
146 void CurrentMgr::createManager(const QString
&filename
, const QString
&dbusObjectName
) {
148 kDebug()<<"ERROR calling createManager twice";
149 disconnect(m_mgr
, 0, 0, 0);
150 // still todo - delete old m_mgr
153 kDebug()<<"DBus Object name: "<<dbusObjectName
;
154 m_mgr
= KBookmarkManager::managerForFile(filename
, dbusObjectName
);
157 m_model
->setRoot(root());
159 m_model
= new KBookmarkModel(root());
162 connect(m_mgr
, SIGNAL( changed(const QString
&, const QString
&) ),
163 SLOT( slotBookmarksChanged(const QString
&, const QString
&) ));
166 void CurrentMgr::slotBookmarksChanged(const QString
&, const QString
&) {
167 if(ignorenext
> 0) //We ignore the first changed signal after every change we did
173 m_model
->setRoot(m_mgr
->root());
175 CmdHistory::self()->clearHistory();
176 KEBApp::self()->updateActions();
177 KEBApp::self()->expandAll();
180 void CurrentMgr::notifyManagers(const KBookmarkGroup
& grp
)
183 mgr()->emitChanged(grp
);
186 void CurrentMgr::notifyManagers() {
187 notifyManagers( root() );
190 void CurrentMgr::reloadConfig() {
191 mgr()->emitConfigChanged();
194 QString
CurrentMgr::makeTimeStr(const QString
& in
)
198 secs
= in
.toInt(&ok
);
201 return makeTimeStr(secs
);
204 QString
CurrentMgr::makeTimeStr(int b
)
208 return (dt
.daysTo(QDateTime::currentDateTime()) > 31)
209 ? KGlobal::locale()->formatDate(dt
.date(), KLocale::LongDate
)
210 : KGlobal::locale()->formatDateTime(dt
, KLocale::LongDate
);
213 /* -------------------------- */
214 #include <QtDBus/QDBusConnection>
215 KEBApp
*KEBApp::s_topLevel
= 0;
218 const QString
&bookmarksFile
, bool readonly
,
219 const QString
&address
, bool browser
, const QString
&caption
,
220 const QString
&dbusObjectName
221 ) : KXmlGuiWindow(), m_bookmarksFilename(bookmarksFile
),
223 m_dbusObjectName(dbusObjectName
), m_readOnly(readonly
),m_browser(browser
)
225 QDBusConnection::sessionBus().registerObject("/keditbookmarks", this, QDBusConnection::ExportScriptableSlots
);
226 Q_UNUSED(address
);//FIXME sets the current item
228 m_cmdHistory
= new CmdHistory(actionCollection());
236 createGUI("keditbookmarks-genui.rc");
238 connect(qApp
->clipboard(), SIGNAL( dataChanged() ),
239 SLOT( slotClipboardDataChanged() ));
241 KGlobal::locale()->insertCatalog("libkonq");
245 CurrentMgr::self()->createManager(m_bookmarksFilename
, m_dbusObjectName
);
247 mBookmarkListView
= new BookmarkListView();
248 mBookmarkListView
->setModel( CurrentMgr::self()->model() );
249 mBookmarkListView
->setSelectionMode(QAbstractItemView::ExtendedSelection
);
250 mBookmarkListView
->loadColumnSetting();
252 KViewSearchLineWidget
*searchline
= new KViewSearchLineWidget(mBookmarkListView
);
254 mBookmarkFolderView
= new BookmarkFolderView(mBookmarkListView
);
257 QWidget
* rightSide
= new QWidget
;
258 QVBoxLayout
*listLayout
= new QVBoxLayout(rightSide
);
259 rightSide
->setLayout(listLayout
);
260 listLayout
->addWidget(searchline
);
261 listLayout
->addWidget(mBookmarkListView
);
263 m_bkinfo
= new BookmarkInfoWidget(mBookmarkListView
);
265 listLayout
->addWidget(m_bkinfo
);
267 QSplitter
*hsplitter
= new QSplitter(this);
268 hsplitter
->setOrientation(Qt::Horizontal
);
269 hsplitter
->addWidget(mBookmarkFolderView
);
270 hsplitter
->addWidget(rightSide
);
271 hsplitter
->setStretchFactor(1,1);
273 setCentralWidget(hsplitter
);
275 mBookmarkListView
->expandAll();
277 slotClipboardDataChanged();
278 setAutoSaveSettings();
280 connect(mBookmarkListView
->selectionModel(), SIGNAL(selectionChanged( const QItemSelection
&, const QItemSelection
& )),
281 this, SLOT(selectionChanged()));
283 connect(mBookmarkFolderView
->selectionModel(), SIGNAL(selectionChanged( const QItemSelection
&, const QItemSelection
& )),
284 this, SLOT(selectionChanged()));
286 setCancelFavIconUpdatesEnabled(false);
287 setCancelTestsEnabled(false);
291 void KEBApp::expandAll()
293 mBookmarkListView
->expandAll();
296 void KEBApp::collapseAll()
298 mBookmarkListView
->collapseAll();
301 QString
KEBApp::bookmarkFilename()
303 return m_bookmarksFilename
;
306 void KEBApp::reset(const QString
& caption
, const QString
& bookmarksFileName
)
308 //FIXME check this code, probably should be model()->setRoot instead of resetModel()
310 m_bookmarksFilename
= bookmarksFileName
;
311 CurrentMgr::self()->createManager(m_bookmarksFilename
, m_dbusObjectName
); //FIXME this is still a memory leak (iff called by slotLoad)
312 CurrentMgr::self()->model()->resetModel();
313 mBookmarkListView
->expandAll();
317 void KEBApp::startEdit( Column c
)
319 const QModelIndexList
& list
= mBookmarkListView
->selectionModel()->selectedIndexes();
320 QModelIndexList::const_iterator it
, end
;
321 end
= list
.constEnd();
322 for(it
= list
.constBegin(); it
!= end
; ++it
)
323 if( (*it
).column() == int(c
) && (mBookmarkListView
->model()->flags(*it
) & Qt::ItemIsEditable
) )
324 return mBookmarkListView
->edit( *it
);
327 //FIXME clean up and remove unneeded things
328 SelcAbilities
KEBApp::getSelectionAbilities() const
330 SelcAbilities selctionAbilities
;
331 selctionAbilities
.itemSelected
= false;
332 selctionAbilities
.group
= false;
333 selctionAbilities
.separator
= false;
334 selctionAbilities
.urlIsEmpty
= false;
335 selctionAbilities
.root
= false;
336 selctionAbilities
.multiSelect
= false;
337 selctionAbilities
.singleSelect
= false;
338 selctionAbilities
.notEmpty
= false;
339 selctionAbilities
.deleteEnabled
= false;
342 QModelIndexList sel
= mBookmarkListView
->selectionModel()->selectedIndexes();
346 nbk
= mBookmarkListView
->bookmarkForIndex(sel
.first());
347 columnCount
= mBookmarkListView
->model()->columnCount();
351 sel
= mBookmarkFolderView
->selectionModel()->selectedIndexes();
353 nbk
= mBookmarkFolderView
->bookmarkForIndex(sel
.first());
354 columnCount
= mBookmarkFolderView
->model()->columnCount();
357 if ( sel
.count() > 0)
359 selctionAbilities
.deleteEnabled
= true;
360 selctionAbilities
.itemSelected
= true;
361 selctionAbilities
.group
= nbk
.isGroup();
362 selctionAbilities
.separator
= nbk
.isSeparator();
363 selctionAbilities
.urlIsEmpty
= nbk
.url().isEmpty();
364 selctionAbilities
.root
= nbk
.address() == CurrentMgr::self()->root().address();
365 selctionAbilities
.multiSelect
= (sel
.count() > columnCount
);
366 selctionAbilities
.singleSelect
= (!selctionAbilities
.multiSelect
&& selctionAbilities
.itemSelected
);
368 //FIXME check next line, if it actually works
369 selctionAbilities
.notEmpty
= CurrentMgr::self()->root().first().hasParent();
372 <<"\nsa.itemSelected "<<selctionAbilities.itemSelected
373 <<"\nsa.group "<<selctionAbilities.group
374 <<"\nsa.separator "<<selctionAbilities.separator
375 <<"\nsa.urlIsEmpty "<<selctionAbilities.urlIsEmpty
376 <<"\nsa.root "<<selctionAbilities.root
377 <<"\nsa.multiSelect "<<selctionAbilities.multiSelect
378 <<"\nsa.singleSelect "<<selctionAbilities.singleSelect
379 <<"\nsa.deleteEnabled"<<selctionAbilities.deleteEnabled
382 return selctionAbilities
;
385 void KEBApp::setActionsEnabled(SelcAbilities sa
) {
386 KActionCollection
* coll
= actionCollection();
388 QStringList toEnable
;
390 if (sa
.multiSelect
|| (sa
.singleSelect
&& !sa
.root
))
391 toEnable
<< "edit_copy";
393 if (sa
.multiSelect
|| (sa
.singleSelect
&& !sa
.root
&& !sa
.urlIsEmpty
&& !sa
.group
&& !sa
.separator
))
394 toEnable
<< "openlink";
398 toEnable
<< "testall" << "updateallfavicons";
400 if ( sa
.deleteEnabled
&& (sa
.multiSelect
|| (sa
.singleSelect
&& !sa
.root
)) )
401 toEnable
<< "delete" << "edit_cut";
405 toEnable
<< "edit_paste";
407 if( sa
.multiSelect
|| (sa
.singleSelect
&& !sa
.root
&& !sa
.urlIsEmpty
&& !sa
.group
&& !sa
.separator
))
408 toEnable
<< "testlink" << "updatefavicon";
410 if (sa
.singleSelect
&& !sa
.root
&& !sa
.separator
) {
411 toEnable
<< "rename" << "changeicon" << "changecomment";
413 toEnable
<< "changeurl";
416 if (sa
.singleSelect
) {
417 toEnable
<< "newfolder" << "newbookmark" << "insertseparator";
419 toEnable
<< "sort" << "recursivesort" << "setastoolbar";
423 for ( QStringList::const_iterator it
= toEnable
.constBegin();
424 it
!= toEnable
.constEnd(); ++it
)
426 //kDebug() <<" enabling action "<<(*it);
427 coll
->action((*it
).toAscii().data())->setEnabled(true);
431 KBookmark
KEBApp::firstSelected() const
434 const QModelIndexList
& list
= mBookmarkListView
->selectionModel()->selectedIndexes();
435 if(list
.count()) // selection in main listview, return bookmark for firstSelected
436 return mBookmarkListView
->bookmarkForIndex(*list
.constBegin());
438 // no selection in main listview, fall back to selection in left tree
439 const QModelIndexList
& list2
= mBookmarkFolderView
->selectionModel()->selectedIndexes();
440 return mBookmarkFolderView
->bookmarkForIndex(*list2
.constBegin());
443 QString
KEBApp::insertAddress() const
445 KBookmark current
= firstSelected();
446 return (current
.isGroup())
447 ? (current
.address() + "/0") //FIXME internal represantation used
448 : KBookmark::nextAddress(current
.address());
451 bool lessAddress(const QString
& first
, const QString
& second
)
459 QString
error("ERROR");
470 uint aEnd
= a
.length();
471 uint bEnd
= b
.length();
472 // Each iteration checks one "/"-delimeted part of the address
473 // "" is treated correctly
476 // Invariant: a[0 ... aLast] == b[0 ... bLast]
477 if(aLast
+ 1 == aEnd
) //The last position was the last slash
478 return true; // That means a is shorter than b
482 uint aNext
= a
.indexOf("/", aLast
+ 1);
483 uint bNext
= b
.indexOf("/", bLast
+ 1);
486 uint aNum
= a
.mid(aLast
+ 1, aNext
- aLast
- 1).toUInt(&okay
);
489 uint bNum
= b
.mid(bLast
+ 1, bNext
- bLast
- 1).toUInt(&okay
);
501 bool lessBookmark(const KBookmark
& first
, const KBookmark
& second
) //FIXME Using internal represantation
503 return lessAddress(first
.address(), second
.address());
506 KBookmark::List
KEBApp::allBookmarks() const
508 KBookmark::List bookmarks
;
509 selectedBookmarksExpandedHelper(CurrentMgr::self()->root(), bookmarks
);
513 KBookmark::List
KEBApp::selectedBookmarks() const
515 KBookmark::List bookmarks
;
516 const QModelIndexList
& list
= mBookmarkListView
->selectionModel()->selectedIndexes();
517 if (!list
.isEmpty()) {
518 QModelIndexList::const_iterator it
, end
;
519 end
= list
.constEnd();
520 for( it
= list
.constBegin(); it
!= end
; ++it
) {
521 if((*it
).column() != 0)
523 KBookmark bk
= mBookmarkListView
->bookmarkModel()->bookmarkForIndex(*it
);;
524 if(bk
.address() != CurrentMgr::self()->root().address())
525 bookmarks
.push_back( bk
);
527 qSort(bookmarks
.begin(), bookmarks
.end(), lessBookmark
);
529 bookmarks
.push_back(firstSelected());
535 KBookmark::List
KEBApp::selectedBookmarksExpanded() const
537 KBookmark::List bookmarks
= selectedBookmarks();
538 KBookmark::List result
;
539 KBookmark::List::const_iterator it
, end
;
540 end
= bookmarks
.constEnd();
541 for(it
= bookmarks
.constBegin(); it
!= end
; ++it
)
543 selectedBookmarksExpandedHelper( *it
, result
);
548 void KEBApp::selectedBookmarksExpandedHelper(const KBookmark
& bk
, KBookmark::List
& bookmarks
) const
550 //FIXME in which order parents should ideally be: parent then child
551 // or child and then parents
554 KBookmarkGroup parent
= bk
.toGroup();
555 KBookmark child
= parent
.first();
556 while(!child
.isNull())
558 selectedBookmarksExpandedHelper(child
, bookmarks
);
559 child
= parent
.next(child
);
564 bookmarks
.push_back( bk
);
568 void KEBApp::updateStatus(const QString
&url
)
570 if(m_bkinfo
->bookmark().url() == url
)
571 m_bkinfo
->updateStatus();
577 delete ActionsImpl::self();
578 delete mBookmarkListView
;
579 delete CurrentMgr::self();
582 KToggleAction
* KEBApp::getToggleAction(const char *action
) const {
583 return static_cast<KToggleAction
*>(actionCollection()->action(action
));
586 void KEBApp::resetActions() {
587 stateChanged("disablestuff");
588 stateChanged("normal");
591 stateChanged("notreadonly");
594 void KEBApp::selectionChanged()
599 void KEBApp::updateActions() {
601 setActionsEnabled(getSelectionAbilities());
604 void KEBApp::slotClipboardDataChanged() {
605 // kDebug() << "KEBApp::slotClipboardDataChanged";
607 m_canPaste
= KBookmark::List::canDecode(
608 QApplication::clipboard()->mimeData());
613 /* -------------------------- */
615 void KEBApp::notifyCommandExecuted() {
616 // kDebug() << "KEBApp::notifyCommandExecuted()";
620 /* -------------------------- */
622 void KEBApp::slotConfigureToolbars() {
623 saveMainWindowSettings(KConfigGroup( KGlobal::config(), "MainWindow") );
624 KEditToolBar
dlg(actionCollection(), this);
625 connect(&dlg
, SIGNAL( newToolBarConfig() ),
626 SLOT( slotNewToolbarConfig() ));
630 void KEBApp::slotNewToolbarConfig() {
631 // called when OK or Apply is clicked
633 applyMainWindowSettings(KConfigGroup(KGlobal::config(), "MainWindow") );
636 /* -------------------------- */
638 #include "toplevel.moc"