diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-11-22 18:41:30 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-11-22 18:41:30 +0900 |
commit | ee0d99607c14cb63d3ebdb3a970b508949fa8219 (patch) | |
tree | 94ac1efedb94cb38bf6879ba0610fe75b554216b /src/digikam/timelineview.cpp | |
parent | 4adff739380e4ae9f30e443ee95644f184456869 (diff) | |
download | digikam-ee0d99607c14cb63d3ebdb3a970b508949fa8219.tar.gz digikam-ee0d99607c14cb63d3ebdb3a970b508949fa8219.zip |
Rename 'digikam' folder to 'src'
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'src/digikam/timelineview.cpp')
-rw-r--r-- | src/digikam/timelineview.cpp | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/src/digikam/timelineview.cpp b/src/digikam/timelineview.cpp new file mode 100644 index 00000000..ae8a6bc2 --- /dev/null +++ b/src/digikam/timelineview.cpp @@ -0,0 +1,645 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2007-12-08 + * Description : Time line sidebar tab contents. + * + * Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com> + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// TQt includes. + +#include <tqtimer.h> +#include <tqframe.h> +#include <tqhbox.h> +#include <tqlayout.h> +#include <tqcombobox.h> +#include <tqpushbutton.h> +#include <tqhbuttongroup.h> +#include <tqmap.h> +#include <tqscrollbar.h> +#include <tqwhatsthis.h> +#include <tqtooltip.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeconfig.h> +#include <kdialog.h> +#include <klineedit.h> +#include <kiconloader.h> +#include <tdeapplication.h> +#include <ksqueezedtextlabel.h> +#include <kstandarddirs.h> +#include <tdeversion.h> +#include <tdemessagebox.h> + +#if KDE_IS_VERSION(3,2,0) +#include <kinputdialog.h> +#else +#include <klineeditdlg.h> +#endif + +// Local includes. + +#include "album.h" +#include "albummanager.h" +#include "ddebug.h" +#include "searchtextbar.h" +#include "timelinefolderview.h" +#include "timelinewidget.h" +#include "timelineview.h" +#include "timelineview.moc" + +namespace Digikam +{ + +class TimeLineViewPriv +{ + +public: + + TimeLineViewPriv() + { + timeUnitCB = 0; + scaleBG = 0; + cursorDateLabel = 0; + cursorCountLabel = 0; + timeLineWidget = 0; + timer = 0; + resetButton = 0; + saveButton = 0; + scrollBar = 0; + timeLineFolderView = 0; + nameEdit = 0; + searchDateBar = 0; + } + + TQScrollBar *scrollBar; + + TQTimer *timer; + + TQComboBox *timeUnitCB; + + TQHButtonGroup *scaleBG; + + TQPushButton *resetButton; + TQPushButton *saveButton; + + TQLabel *cursorCountLabel; + + KLineEdit *nameEdit; + + KSqueezedTextLabel *cursorDateLabel; + + SearchTextBar *searchDateBar; + + TimeLineWidget *timeLineWidget; + + TimeLineFolderView *timeLineFolderView; +}; + +TimeLineView::TimeLineView(TQWidget *parent) + : TQWidget(parent, 0, TQt::WDestructiveClose) +{ + d = new TimeLineViewPriv; + d->timer = new TQTimer(this); + + TQVBoxLayout *vlay = new TQVBoxLayout(this); + TQFrame *panel = new TQFrame(this); + panel->setFrameStyle(TQFrame::StyledPanel | TQFrame::Sunken); + panel->setLineWidth(1); + + TQGridLayout *grid = new TQGridLayout(panel, 4, 3); + + // --------------------------------------------------------------- + + TQWidget *hbox1 = new TQWidget(panel); + TQHBoxLayout *hlay = new TQHBoxLayout(hbox1); + + TQLabel *label1 = new TQLabel(i18n("Time Unit:"), hbox1); + d->timeUnitCB = new TQComboBox(false, hbox1); + d->timeUnitCB->insertItem(i18n("Day"), TimeLineWidget::Day); + d->timeUnitCB->insertItem(i18n("Week"), TimeLineWidget::Week); + d->timeUnitCB->insertItem(i18n("Month"), TimeLineWidget::Month); + d->timeUnitCB->insertItem(i18n("Year"), TimeLineWidget::Year); + d->timeUnitCB->setCurrentItem((int)TimeLineWidget::Month); + d->timeUnitCB->setFocusPolicy(TQWidget::NoFocus); + TQWhatsThis::add(d->timeUnitCB, i18n("<p>Select the histogram time unit here.<p>" + "You can change the graph decade to zoom in or zoom out over time.")); + + d->scaleBG = new TQHButtonGroup(hbox1); + d->scaleBG->setExclusive(true); + d->scaleBG->setFrameShape(TQFrame::NoFrame); + d->scaleBG->setInsideMargin( 0 ); + TQWhatsThis::add(d->scaleBG, i18n("<p>Select the histogram scale here.<p>" + "If the date count's maximal values are small, you can use the linear scale.<p>" + "Logarithmic scale can be used when the maximal values are big; " + "if it is used, all values (small and large) will be visible on the " + "graph.")); + + TQPushButton *linHistoButton = new TQPushButton( d->scaleBG ); + TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) ); + d->scaleBG->insert(linHistoButton, TimeLineWidget::LinScale); + TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png"); + linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) ); + linHistoButton->setToggleButton(true); + + TQPushButton *logHistoButton = new TQPushButton( d->scaleBG ); + TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) ); + d->scaleBG->insert(logHistoButton, TimeLineWidget::LogScale); + TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png"); + logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) ); + logHistoButton->setToggleButton(true); + + hlay->setMargin(0); + hlay->setSpacing(KDialog::spacingHint()); + hlay->addWidget(label1); + hlay->addWidget(d->timeUnitCB); + hlay->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); + hlay->addWidget(d->scaleBG); + + // --------------------------------------------------------------- + + d->timeLineWidget = new TimeLineWidget(panel); + d->scrollBar = new TQScrollBar(panel); + d->scrollBar->setOrientation(TQt::Horizontal); + d->scrollBar->setMinValue(0); + d->scrollBar->setLineStep(1); + + d->cursorDateLabel = new KSqueezedTextLabel(0, panel); + d->cursorCountLabel = new TQLabel(panel); + d->cursorCountLabel->setAlignment(TQt::AlignRight); + + // --------------------------------------------------------------- + + TQHBox *hbox2 = new TQHBox(panel); + hbox2->setMargin(0); + hbox2->setSpacing(KDialog::spacingHint()); + + d->resetButton = new TQPushButton(hbox2); + d->resetButton->setPixmap(SmallIcon("reload_page")); + TQToolTip::add(d->resetButton, i18n("Clear current selection")); + TQWhatsThis::add(d->resetButton, i18n("<p>If you press this button, current " + "dates selection from time-line will be " + "clear.")); + d->nameEdit = new KLineEdit(hbox2); + TQWhatsThis::add(d->nameEdit, i18n("<p>Enter the name of the current dates search to save in the " + "\"My Date Searches\" view")); + + d->saveButton = new TQPushButton(hbox2); + d->saveButton->setPixmap(SmallIcon("document-save")); + d->saveButton->setEnabled(false); + TQToolTip::add(d->saveButton, i18n("Save current selection to a new virtual Album")); + TQWhatsThis::add(d->saveButton, i18n("<p>If you press this button, current " + "dates selection from time-line will be " + "saved to a new search virtual Album using name " + "set on the left side.")); + + // --------------------------------------------------------------- + + grid->addMultiCellWidget(hbox1, 0, 0, 0, 3); + grid->addMultiCellWidget(d->cursorDateLabel, 1, 1, 0, 2); + grid->addMultiCellWidget(d->cursorCountLabel, 1, 1, 3, 3); + grid->addMultiCellWidget(d->timeLineWidget, 2, 2, 0, 3); + grid->addMultiCellWidget(d->scrollBar, 3, 3, 0, 3); + grid->addMultiCellWidget(hbox2, 4, 4, 0, 3); + grid->setColStretch(2, 10); + grid->setMargin(KDialog::spacingHint()); + grid->setSpacing(KDialog::spacingHint()); + + // --------------------------------------------------------------- + + d->timeLineFolderView = new TimeLineFolderView(this); + d->searchDateBar = new SearchTextBar(this, "TimeLineViewSearchDateBar"); + + vlay->addWidget(panel); + vlay->addWidget(d->timeLineFolderView); + vlay->addItem(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::Minimum)); + vlay->addWidget(d->searchDateBar); + vlay->setMargin(0); + vlay->setSpacing(0); + + // --------------------------------------------------------------- + + connect(AlbumManager::instance(), TQ_SIGNAL(signalDatesMapDirty(const TQMap<TQDateTime, int>&)), + d->timeLineWidget, TQ_SLOT(slotDatesMap(const TQMap<TQDateTime, int>&))); + + connect(d->timeLineFolderView, TQ_SIGNAL(signalAlbumSelected(SAlbum*)), + this, TQ_SLOT(slotAlbumSelected(SAlbum*))); + + connect(d->timeLineFolderView, TQ_SIGNAL(signalRenameAlbum(SAlbum*)), + this, TQ_SLOT(slotRenameAlbum(SAlbum*))); + + connect(d->timeLineFolderView, TQ_SIGNAL(signalTextSearchFilterMatch(bool)), + d->searchDateBar, TQ_SLOT(slotSearchResult(bool))); + + connect(d->searchDateBar, TQ_SIGNAL(signalTextChanged(const TQString&)), + d->timeLineFolderView, TQ_SLOT(slotTextSearchFilterChanged(const TQString&))); + + connect(d->timeUnitCB, TQ_SIGNAL(activated(int)), + this, TQ_SLOT(slotTimeUnitChanged(int))); + + connect(d->scaleBG, TQ_SIGNAL(released(int)), + this, TQ_SLOT(slotScaleChanged(int))); + + connect(d->timeLineWidget, TQ_SIGNAL(signalDateMapChanged()), + this, TQ_SLOT(slotInit())); + + connect(d->timeLineWidget, TQ_SIGNAL(signalCursorPositionChanged()), + this, TQ_SLOT(slotCursorPositionChanged())); + + connect(d->timeLineWidget, TQ_SIGNAL(signalSelectionChanged()), + this, TQ_SLOT(slotSelectionChanged())); + + connect(d->timeLineWidget, TQ_SIGNAL(signalRefDateTimeChanged()), + this, TQ_SLOT(slotRefDateTimeChanged())); + + connect(d->timer, TQ_SIGNAL(timeout()), + this, TQ_SLOT(slotUpdateCurrentDateSearchAlbum())); + + connect(d->resetButton, TQ_SIGNAL(clicked()), + this, TQ_SLOT(slotResetSelection())); + + connect(d->saveButton, TQ_SIGNAL(clicked()), + this, TQ_SLOT(slotSaveSelection())); + + connect(d->scrollBar, TQ_SIGNAL(valueChanged(int)), + this, TQ_SLOT(slotScrollBarValueChanged(int))); + + connect(d->nameEdit, TQ_SIGNAL(textChanged(const TQString&)), + this, TQ_SLOT(slotCheckAboutSelection())); + + connect(d->nameEdit, TQ_SIGNAL(returnPressed(const TQString&)), + d->saveButton, TQ_SLOT(animateClick())); +} + +TimeLineView::~TimeLineView() +{ + writeConfig(); + delete d->timer; + delete d; +} + +TimeLineFolderView* TimeLineView::folderView() const +{ + return d->timeLineFolderView; +} + +SearchTextBar* TimeLineView::searchBar() const +{ + return d->searchDateBar; +} + +void TimeLineView::slotInit() +{ + // Date Maps are loaded from AlbumManager to TimeLineWidget after than GUI is initialized. + // AlbumManager query Date TDEIO slave to stats items from database and it can take a while. + // We waiting than TimeLineWidget is ready before to set last config from users. + + readConfig(); + + disconnect(d->timeLineWidget, TQ_SIGNAL(signalDateMapChanged()), + this, TQ_SLOT(slotInit())); + + connect(d->timeLineWidget, TQ_SIGNAL(signalDateMapChanged()), + this, TQ_SLOT(slotCursorPositionChanged())); +} + +void TimeLineView::readConfig() +{ + TDEConfig* config = kapp->config(); + config->setGroup("TimeLine SideBar"); + + d->timeUnitCB->setCurrentItem(config->readNumEntry("Histogram TimeUnit", TimeLineWidget::Month)); + slotTimeUnitChanged(d->timeUnitCB->currentItem()); + + d->scaleBG->setButton(config->readNumEntry("Histogram Scale", TimeLineWidget::LinScale)); + slotScaleChanged(d->scaleBG->selectedId()); + + TQDateTime now = TQDateTime::currentDateTime(); + d->timeLineWidget->setCursorDateTime(config->readDateTimeEntry("Cursor Position", &now)); + d->timeLineWidget->setCurrentIndex(d->timeLineWidget->indexForCursorDateTime()); +} + +void TimeLineView::writeConfig() +{ + TDEConfig* config = kapp->config(); + config->setGroup("TimeLine SideBar"); + config->writeEntry("Histogram TimeUnit", d->timeUnitCB->currentItem()); + config->writeEntry("Histogram Scale", d->scaleBG->selectedId()); + config->writeEntry("Cursor Position", d->timeLineWidget->cursorDateTime()); + config->sync(); +} + +void TimeLineView::setActive(bool val) +{ + if (d->timeLineFolderView->selectedItem()) + { + d->timeLineFolderView->setActive(val); + } + else if (val) + { + int totalCount = 0; + DateRangeList list = d->timeLineWidget->selectedDateRange(totalCount); + if (list.isEmpty()) + { + AlbumManager::instance()->setCurrentAlbum(0); + } + else + { + AlbumList sList = AlbumManager::instance()->allSAlbums(); + for (AlbumList::iterator it = sList.begin(); it != sList.end(); ++it) + { + SAlbum* salbum = (SAlbum*)(*it); + if (salbum->title() == d->timeLineFolderView->currentTimeLineSearchName()) + AlbumManager::instance()->setCurrentAlbum(salbum); + } + } + } +} + +void TimeLineView::slotRefDateTimeChanged() +{ + d->scrollBar->blockSignals(true); + d->scrollBar->setMaxValue(d->timeLineWidget->totalIndex()-1); + d->scrollBar->setValue(d->timeLineWidget->indexForRefDateTime()-1); + d->scrollBar->blockSignals(false); +} + +void TimeLineView::slotTimeUnitChanged(int mode) +{ + d->timeLineWidget->setTimeUnit((TimeLineWidget::TimeUnit)mode); +} + +void TimeLineView::slotScrollBarValueChanged(int val) +{ + d->timeLineWidget->setCurrentIndex(val); +} + +void TimeLineView::slotScaleChanged(int mode) +{ + d->timeLineWidget->setScaleMode((TimeLineWidget::ScaleMode)mode); +} + +void TimeLineView::slotCursorPositionChanged() +{ + TQString txt; + int val = d->timeLineWidget->cursorInfo(txt); + d->cursorDateLabel->setText(txt); + d->cursorCountLabel->setText(TQString::number(val)); +} + +void TimeLineView::slotSelectionChanged() +{ + d->timer->start(100, true); +} + +/** Called from d->timer event.*/ +void TimeLineView::slotUpdateCurrentDateSearchAlbum() +{ + slotCheckAboutSelection(); + createNewDateSearchAlbum(d->timeLineFolderView->currentTimeLineSearchName()); +} + +void TimeLineView::slotSaveSelection() +{ + TQString name = d->nameEdit->text(); + if (!checkName(name)) + return; + createNewDateSearchAlbum(name); +} + +void TimeLineView::createNewDateSearchAlbum(const TQString& name) +{ + int totalCount = 0; + TQDateTime start, end; + DateRangeList list = d->timeLineWidget->selectedDateRange(totalCount); + + if (list.isEmpty()) + { + AlbumManager::instance()->setCurrentAlbum(0); + return; + } + + d->timeLineFolderView->blockSignals(true); + d->timeLineFolderView->clearSelection(); + d->timeLineFolderView->blockSignals(false); + + // We will make now the Url for digiKam Search TDEIO-Slave + + KURL url; + url.setProtocol("digikamsearch"); + + int grp = list.count(); + TQString path("1 AND 2"); + + if (grp > 1 ) + { + for (int i = 1 ; i < grp; i++) + { + path.append(" OR "); + path.append(TQString("%1 AND %2").arg(i*2+1).arg(i*2+2)); + } + } + url.setPath(path); + + int i = 0; + DateRangeList::iterator it; + for (it = list.begin() ; it != list.end(); ++it) + { + start = (*it).first; + end = (*it).second; + url.addQueryItem(TQString("%1.key").arg(i*2+1), TQString("imagedate")); + url.addQueryItem(TQString("%1.op").arg(i*2+1), TQString("GT")); + url.addQueryItem(TQString("%1.val").arg(i*2+1), start.date().toString(TQt::ISODate)); + url.addQueryItem(TQString("%1.key").arg(i*2+2), TQString("imagedate")); + url.addQueryItem(TQString("%1.op").arg(i*2+2), TQString("LT")); + url.addQueryItem(TQString("%1.val").arg(i*2+2), end.date().toString(TQt::ISODate)); + i++; + } + + url.addQueryItem("name", name); + url.addQueryItem("count", TQString::number(grp*2)); + url.addQueryItem("type", TQString("datesearch")); + + //DDebug() << url << endl; + + SAlbum* album = AlbumManager::instance()->createSAlbum(url, false); + AlbumManager::instance()->setCurrentAlbum(album); +} + +void TimeLineView::slotAlbumSelected(SAlbum* salbum) +{ + if (!salbum) + { + slotResetSelection(); + return; + } + + // Date Search url for TDEIO-Slave is something like that : + // digikamsearch:1 AND 2 OR 3 AND 4 OR 5 AND 6? + // 1.key=imagedate&1.op=GT&1.val=2006-02-06& + // 2.key=imagedate&2.op=LT&2.val=2006-02-07& + // 3.key=imagedate&3.op=GT&3.val=2006-02-10& + // 4.key=imagedate&4.op=LT&4.val=2006-02-11& + // 5.key=imagedate&5.op=GT&5.val=2006-02-12& + // 6.key=imagedate&6.op=LT&6.val=2006-02-13& + // name=TimeLineSelection& + // count=6 + // type=datesearch + + // Check if a special url query exist to identify a SAlbum dedicaced to Date Search + KURL url = salbum->kurl(); + TQMap<TQString, TQString> queries = url.queryItems(); + if (queries.isEmpty()) return; + + TQString type = url.queryItem("type"); + if (type != TQString("datesearch")) return; + + bool ok = false; + int count = url.queryItem("count").toInt(&ok); + if (!ok || count <= 0) return; + + //DDebug() << url << endl; + + TQMap<TQString, TQString>::iterator it2; + TQString key; + TQDateTime start, end; + DateRangeList list; + for (int i = 1 ; i <= count ; i+=2) + { + key = TQString("%1.val").arg(TQString::number(i)); + it2 = queries.find(key); + if (it2 != queries.end()) + start = TQDateTime(TQDate::fromString(it2.data(), TQt::ISODate)); + + //DDebug() << key << " :: " << it2.data() << endl; + + key = TQString("%1.val").arg(TQString::number(i+1)); + it2 = queries.find(key); + if (it2 != queries.end()) + end = TQDateTime(TQDate::fromString(it2.data(), TQt::ISODate)); + + //DDebug() << key << " :: " << it2.data() << endl; + + list.append(DateRange(start, end)); + } + + /* + DateRangeList::iterator it3; + for (it3 = list.begin() ; it3 != list.end(); ++it3) + DDebug() << (*it3).first.date().toString(TQt::ISODate) << " :: " + << (*it3).second.date().toString(TQt::ISODate) << endl; + */ + + d->timeLineWidget->setSelectedDateRange(list); + AlbumManager::instance()->setCurrentAlbum(salbum); +} + +void TimeLineView::slotResetSelection() +{ + d->timeLineWidget->slotResetSelection(); + slotCheckAboutSelection(); + AlbumManager::instance()->setCurrentAlbum(0); +} + +bool TimeLineView::checkName(TQString& name) +{ + bool checked = checkAlbum(name); + + while (!checked) + { + TQString label = i18n( "Search name already exists.\n" + "Please enter a new name:" ); + bool ok; +#if KDE_IS_VERSION(3,2,0) + TQString newTitle = KInputDialog::getText(i18n("Name exists"), label, name, &ok, this); +#else + TQString newTitle = KLineEditDlg::getText(i18n("Name exists"), label, name, ok, this); +#endif + if (!ok) return false; + + name = newTitle; + checked = checkAlbum(name); + } + + return true; +} + +bool TimeLineView::checkAlbum(const TQString& name) const +{ + AlbumList list = AlbumManager::instance()->allSAlbums(); + + for (AlbumList::Iterator it = list.begin() ; it != list.end() ; ++it) + { + SAlbum *album = (SAlbum*)(*it); + if ( album->title() == name ) + return false; + } + return true; +} + +void TimeLineView::slotCheckAboutSelection() +{ + int totalCount = 0; + DateRangeList list = d->timeLineWidget->selectedDateRange(totalCount); + if (!list.isEmpty()) + { + d->nameEdit->setEnabled(true); + + if (!d->nameEdit->text().isEmpty()) + d->saveButton->setEnabled(true); + } + else + { + d->nameEdit->setEnabled(false); + d->saveButton->setEnabled(false); + } +} + +void TimeLineView::slotRenameAlbum(SAlbum* salbum) +{ + if (!salbum) return; + + TQString oldName(salbum->title()); + bool ok; + +#if KDE_IS_VERSION(3,2,0) + TQString name = KInputDialog::getText(i18n("Rename Album (%1)").arg(oldName), + i18n("Enter new album name:"), + oldName, &ok, this); +#else + TQString name = KLineEditDlg::getText(i18n("Rename Album (%1)").arg(oldName), + i18n("Enter new album name:"), + oldName, &ok, this); +#endif + + if (!ok || name == oldName || name.isEmpty()) return; + + if (!checkName(name)) return; + + KURL url = salbum->kurl(); + url.removeQueryItem("name"); + url.addQueryItem("name", name); + AlbumManager::instance()->updateSAlbum(salbum, url); +} + +} // NameSpace Digikam |