25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
knowit/src/notes.cpp

433 lines
11 KiB

/***************************************************************************
notes.cpp - description
-------------------
begin : sob lis 16 2002
copyright : (C) 2002-2004 by Micha³ Rudolf
email : mrudolf@kdewebdev.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "notes.h"
#include <tqstringlist.h>
#include <tqfile.h>
#include <tqdatetime.h>
#include <tqtextstream.h>
#include <tqtextcodec.h>
#include <tdelocale.h>
#include <tdelistview.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <kmimetype.h>
#include <krun.h>
#include <kurl.h>
#include <tdelistview.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#else
#define VERSION "?"
#endif
void TNoteLink::save(TQTextStream& ts) const
{
if (!link.isEmpty()) {
ts << "\\Link " << link << "\n";
if (!description.isEmpty())
ts << "\\Descr " << description << "\n";
}
}
TQString TNoteLink::text(int fmt) const
{
if (fmt == LinkOnly || description.isEmpty()) return link;
else if (fmt == DescriptionOnly) return description;
else if (fmt == LinkDescription)
return TQString("%1 (%2)").arg(link).arg(description);
else return TQString("%1 (%2)").arg(description).arg(link);
}
TQPixmap TNoteLink::icon() const
{
return TDEGlobal::iconLoader()->loadIcon(KMimeType::iconForURL(KURL(link)),
TDEIcon::Small);
}
void TNoteLink::open() const
{
if (!isLocalReference())
new KRun(KURL(link), 0, false, true);
}
void TNoteLink::openWith() const
{
if (!isLocalReference())
KRun::displayOpenWithDialog(KURL(link));
}
bool TNoteLink::isLocalReference() const
{
KURL url(link);
return url.protocol() == "knowit";
}
TNotesCollection::TNotesCollection()
{
Pixmaps[0] = TDEGlobal::iconLoader()->loadIcon("ascii", TDEIcon::Small);
Pixmaps[1] = TDEGlobal::iconLoader()->loadIcon("txt", TDEIcon::Small);
Pixmaps[2] = TDEGlobal::iconLoader()->loadIcon("folder", TDEIcon::Small);
Pixmaps[3] = TDEGlobal::iconLoader()->loadIcon("folder_txt", TDEIcon::Small);
modified = false;
autoUpdate = true;
}
TNotesCollection::~TNotesCollection()
{}
void TNotesCollection::addNote(TQListViewItem* item)
{
insert(item, new TNote(item, this));
TQListViewItem* parent = item->parent();
if (parent) find(parent)->updateView();
modified = true;
}
void TNotesCollection::addNote(TQListViewItem* item, const TQString& s)
{
insert(item, new TNote(item, this, s));
TQListViewItem* parent = item->parent();
if (parent) find(parent)->updateView();
modified = true;
}
void TNotesCollection::removeNote(TQListViewItem* item)
{
TNote* note = find(item);
if (!note) tqWarning("Internal error while removing note\n");
else {
TQListViewItem* parent = item->parent();
for (TQListViewItemIterator it(item); it.current() &&
(it.current() == item || it.current()->depth() > item->depth()); ++it)
find(it.current())->destroy();
delete item;
if (parent) find(parent)->updateView();
modified = true;
}
}
bool TNotesCollection::changeNote(TQListViewItem* item, const TQString& s)
{
TNote* changed = find(item);
if (!changed) {
tqWarning("Internal error while changing note\n");
return false;
}
if (changed->change(s))
return modified = true;
else
return false;
}
void TNotesCollection::clearNotes()
{
setAutoDelete(true);
clear();
setAutoDelete(false);
}
const TQString& TNotesCollection::text(TQListViewItem* item)
{
TNote* note = find(item);
if (!note)
tqFatal("Internal error while accessing note text\n");
return note->text;
}
void TNotesCollection::updateNotesView()
{
for (TQPtrDictIterator<TNote> it(*this); it.current(); ++it)
it.current()->updateView();
}
TNote::TNote(TQListViewItem* i, TNotesCollection* coll) : text()
{
collection = coll;
item = i;
updateView();
}
TNote::TNote(TQListViewItem* i, TNotesCollection* coll, const TQString& s) :
text(s)
{
collection = coll;
item = i;
updateView();
}
bool TNote::isEmpty()
{
return !text.length();
}
bool TNote::contains(const TQString& sought, bool case_sensitive)
{
return text.contains(sought, case_sensitive);
}
TNote::~TNote()
{
}
void TNote::destroy()
{
collection->remove(item);
delete this;
}
bool TNote::change(const TQString& s)
{
if (text == s)
return false;
text = s;
updateView();
return true;
}
TNote::State TNote::state()
{
if (text.stripWhiteSpace().isEmpty())
return (item->childCount()) ? EmptyParent : Empty;
else
return (item->childCount()) ? TextParent : Text;
}
void TNote::updateView()
{
if (collection->autoUpdate)
item->setPixmap(0, collection->Pixmaps[state()]);
}
bool TNote::saveHTML(const KURL& fname, const TQString& origname, const TQString& style,
int flags)
{
TQFile file(fname.path());
if (!file.open( IO_WriteOnly))
return false;
TQTextStream ts(&file);
if (flags & UseUTF8) ts.setEncoding(TQTextStream::UnicodeUTF8);
else ts.setEncoding(TQTextStream::Locale);
ts << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
"<html>\n<head>\n <title>" << i18n("KnowIt document") <<
TQString("</title>\n <meta http-equiv=\"Content-Type\" "
"content=\"text/html; charset=%1\">\n").arg(ts.codec()->mimeName());
if (!style.isEmpty())
ts << " <style type=\"text/css\">\n " << style << "\n </style>\n";
ts << "</head>\n\n<body>\n";
TQValueVector<int> Depths;
Depths.append(0);
if (flags & TOC) {
ts << TQString("<h1>%1</h1>\n").arg(i18n("Table of contents"));
saveHTMLTocEntry(ts, Depths, flags);
ts << "\n\n";
}
Depths.clear();
Depths.append(0);
saveHTMLBuf(ts, Depths, flags);
TQString epilog = i18n("Exported from %1 by KnowIt %2, %3.");
ts << "<br><br><br><small>" << epilog.arg(origname)
.arg(VERSION)
.arg(TQDateTime::currentDateTime().toString()) << "</small>\n\n";
ts << "</body>\n</html>\n\n";
return true;
}
bool TNote::saveHTMLBuf(TQTextStream& ts, TQValueVector<int>& depths,
int flags)
{
int hlevel = depths.count();
depths.last() = depths.last()+1;
if (hlevel < 1) hlevel = 1;
else if (hlevel > 3) hlevel = 3;
TQString id, number;
for (uint i=0; i<depths.count(); i++)
id += TQString("%1.").arg(depths[i]);
if (flags & Enumerate)
number = id + " ";
ts << TQString("<h%1 id=\"S%2\">%3%4</h%5>").arg(hlevel).arg(id).arg(number)
.arg(item->text(0)).arg(hlevel);
TQString htmltext = text;
int begin = htmltext.find("<body");
if (begin >= 0) begin = htmltext.find(">", begin);
int end = htmltext.find("</body>");
if (begin < 0) begin = 0;
if (end <= begin) end = htmltext.length();
ts << htmltext.mid(begin+1, end-begin-1);
/* save links */
for (TQValueList<TNoteLink>::Iterator LinkList = links.begin();
LinkList != links.end(); ++LinkList)
ts << TQString("<a href=\"%1\">%2</a><br>\n").arg((*LinkList).link)
.arg((*LinkList).text(TNoteLink::DescriptionOnly));
/* save rule */
if (flags & AddRule) ts << "<hr size=\"1\" noshade>\n\n";
else ts << "\n\n";
/* save children */
if ((SaveSubnotes | SaveAll) & flags && item->childCount()) {
depths.append(0);
collection->find(item->firstChild())->saveHTMLBuf(ts, depths, flags);
}
if ((SaveSubnotes | SaveAll) & flags && item->nextSibling())
collection->find(item->nextSibling())->saveHTMLBuf(ts, depths, flags);
if (!item->nextSibling()) depths.pop_back();
return true;
}
bool TNote::saveHTMLTocEntry(TQTextStream& ts, TQValueVector<int>& depths, int flags)
{
TQString space;
space.fill(' ', depths.count());
depths.last() = depths.last()+1;
if (depths.last() == 1) {
ts << space;
if (depths.count() != 1) ts << "<dd>";
ts << "<dl>\n";
}
TQString id, number;
for (uint i=0; i<depths.count(); i++)
id += TQString("%1.").arg(depths[i]);
if (flags & Enumerate) number = id + " ";
ts << space;
ts << TQString("<dt><a href=\"#S%1\">%2%3</a></dt>\n").arg(id).arg(number).
arg(item->text(0));
if ((SaveSubnotes | SaveAll) & flags && item->childCount()) {
depths.append(0);
collection->find(item->firstChild())->saveHTMLTocEntry(ts, depths, flags);
}
if ((SaveSubnotes | SaveAll) & flags && item->nextSibling())
collection->find(item->nextSibling())->saveHTMLTocEntry(ts, depths, flags);
if (!item->nextSibling()) {
depths.pop_back();
ts << space;
ts << "</dl>";
if (depths.count()) ts << "</dd>";
ts << "\n";
}
return true;
}
void TNote::addLink(const TQString& s)
{
links.append(TNoteLink(s));
collection->modified = true;
}
void TNote::addLink(const TNoteLink& l)
{
links.append(l);
collection->modified = true;
}
void TNote::removeLink(int i)
{
links.remove(links[i]);
collection->modified = true;
}
void TNote::modifyLink(int i, const TQString& s)
{
links[i].link = s;
collection->modified = true;
}
void TNote::modifyLink(int i, TNoteLink& l)
{
if (l != links[i])
collection->modified = true;
links[i] = l;
}
void TNote::modifyLinkDescription(int i, const TQString& s)
{
links[i].description = s;
collection->modified = true;
}
int TNote::linkCount() const
{
return links.count();
}
const TNoteLink& TNote::link(int i) const
{
return links[i];
}
void TNote::save(TQTextStream& ts, bool current)
{
const TQString header = "\\NewEntry %1 %2\n";
const TQString activeheader = "\\CurrentEntry %1 %2\n";
if (current)
ts << activeheader.arg(item->depth()).arg(item->text(0));
else
ts << header.arg(item->depth()).arg(item->text(0));
for (TQValueList<TNoteLink>::Iterator LinkList = links.begin();
LinkList != links.end(); ++LinkList)
(*LinkList).save(ts);
ts << text;
if (!text.isEmpty())
ts << '\n';
ts << '\n';
}
void TNote::open(TQTextStream& ts)
{
TQString s;
text = "";
links.clear();
while (true) {
s = ts.readLine();
if (s.isNull() || s.isEmpty())
break;
if (s.left(6) == "\\Link ")
addLink(s.mid(6));
else if (s.left(7) == "\\Descr " && links.count())
modifyLinkDescription(links.count()-1, s.mid(7));
else {
if (text.length())
text += '\n';
text += s;
}
}
}