Initial commit

This commit is contained in:
Markus Koch 2014-10-18 18:42:15 +02:00
commit 87e8edeafb
28 changed files with 3227 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pro.user

BIN
KonaClient Executable file

Binary file not shown.

38
KonaClient.pro Executable file
View File

@ -0,0 +1,38 @@
#-------------------------------------------------
#
# Project created by QtCreator 2012-09-03T13:51:11
#
#-------------------------------------------------
QT += core gui network xml
TARGET = KonaClient
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
konasearch.cpp \
konaclient.cpp \
konaimage.cpp \
flowlayout.cpp \
konapreviewimageview.cpp \
konatags.cpp \
konatag.cpp \
konarelatedtags.cpp \
imageviewer.cpp
HEADERS += mainwindow.h \
konasearch.h \
konaclient.h \
konaimage.h \
flowlayout.h \
konapreviewimageview.h \
konatags.h \
konatag.h \
konarelatedtags.h \
imageviewer.h
FORMS += mainwindow.ui \
konapreviewimageview.ui \
imageviewer.ui

404
Makefile Normal file
View File

@ -0,0 +1,404 @@
#############################################################################
# Makefile for building: KonaClient
# Generated by qmake (2.01a) (Qt 4.8.3) on: Do. Mär 28 10:46:21 2013
# Project: KonaClient.pro
# Template: app
# Command: /usr/bin/qmake-qt4 -spec /usr/share/qt4/mkspecs/linux-g++ CONFIG+=debug CONFIG+=declarative_debug -o Makefile KonaClient.pro
#############################################################################
####### Compiler, tools and options
CC = gcc
CXX = g++
DEFINES = -DQT_WEBKIT -DQT_XML_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED
CFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
CXXFLAGS = -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtNetwork -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtXml -I/usr/include/qt4 -I. -I.
LINK = g++
LFLAGS =
LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -lQtXml -lQtGui -lQtNetwork -lQtCore -lpthread
AR = ar cqs
RANLIB =
QMAKE = /usr/bin/qmake-qt4
TAR = tar -cf
COMPRESS = gzip -9f
COPY = cp -f
SED = sed
COPY_FILE = $(COPY)
COPY_DIR = $(COPY) -r
STRIP = strip
INSTALL_FILE = install -m 644 -p
INSTALL_DIR = $(COPY_DIR)
INSTALL_PROGRAM = install -m 755 -p
DEL_FILE = rm -f
SYMLINK = ln -f -s
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
####### Output directory
OBJECTS_DIR = ./
####### Files
SOURCES = main.cpp \
mainwindow.cpp \
konasearch.cpp \
konaclient.cpp \
konaimage.cpp \
flowlayout.cpp \
konapreviewimageview.cpp \
konatags.cpp \
konatag.cpp \
konarelatedtags.cpp \
imageviewer.cpp moc_mainwindow.cpp \
moc_konasearch.cpp \
moc_konaclient.cpp \
moc_konaimage.cpp \
moc_konapreviewimageview.cpp \
moc_konatags.cpp \
moc_konatag.cpp \
moc_konarelatedtags.cpp \
moc_imageviewer.cpp
OBJECTS = main.o \
mainwindow.o \
konasearch.o \
konaclient.o \
konaimage.o \
flowlayout.o \
konapreviewimageview.o \
konatags.o \
konatag.o \
konarelatedtags.o \
imageviewer.o \
moc_mainwindow.o \
moc_konasearch.o \
moc_konaclient.o \
moc_konaimage.o \
moc_konapreviewimageview.o \
moc_konatags.o \
moc_konatag.o \
moc_konarelatedtags.o \
moc_imageviewer.o
DIST = /usr/share/qt4/mkspecs/common/unix.conf \
/usr/share/qt4/mkspecs/common/linux.conf \
/usr/share/qt4/mkspecs/common/gcc-base.conf \
/usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
/usr/share/qt4/mkspecs/common/g++-base.conf \
/usr/share/qt4/mkspecs/common/g++-unix.conf \
/usr/share/qt4/mkspecs/qconfig.pri \
/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \
/usr/share/qt4/mkspecs/features/qt_functions.prf \
/usr/share/qt4/mkspecs/features/qt_config.prf \
/usr/share/qt4/mkspecs/features/exclusive_builds.prf \
/usr/share/qt4/mkspecs/features/default_pre.prf \
/usr/share/qt4/mkspecs/features/debug.prf \
/usr/share/qt4/mkspecs/features/default_post.prf \
/usr/share/qt4/mkspecs/features/declarative_debug.prf \
/usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
/usr/share/qt4/mkspecs/features/warn_on.prf \
/usr/share/qt4/mkspecs/features/qt.prf \
/usr/share/qt4/mkspecs/features/unix/thread.prf \
/usr/share/qt4/mkspecs/features/moc.prf \
/usr/share/qt4/mkspecs/features/resources.prf \
/usr/share/qt4/mkspecs/features/uic.prf \
/usr/share/qt4/mkspecs/features/yacc.prf \
/usr/share/qt4/mkspecs/features/lex.prf \
/usr/share/qt4/mkspecs/features/include_source_dir.prf \
KonaClient.pro
QMAKE_TARGET = KonaClient
DESTDIR =
TARGET = KonaClient
first: all
####### Implicit rules
.SUFFIXES: .o .c .cpp .cc .cxx .C
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
####### Build rules
all: Makefile $(TARGET)
$(TARGET): ui_mainwindow.h ui_konapreviewimageview.h ui_imageviewer.h $(OBJECTS)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
{ test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9]\+\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true
Makefile: KonaClient.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \
/usr/share/qt4/mkspecs/common/linux.conf \
/usr/share/qt4/mkspecs/common/gcc-base.conf \
/usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
/usr/share/qt4/mkspecs/common/g++-base.conf \
/usr/share/qt4/mkspecs/common/g++-unix.conf \
/usr/share/qt4/mkspecs/qconfig.pri \
/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \
/usr/share/qt4/mkspecs/features/qt_functions.prf \
/usr/share/qt4/mkspecs/features/qt_config.prf \
/usr/share/qt4/mkspecs/features/exclusive_builds.prf \
/usr/share/qt4/mkspecs/features/default_pre.prf \
/usr/share/qt4/mkspecs/features/debug.prf \
/usr/share/qt4/mkspecs/features/default_post.prf \
/usr/share/qt4/mkspecs/features/declarative_debug.prf \
/usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
/usr/share/qt4/mkspecs/features/warn_on.prf \
/usr/share/qt4/mkspecs/features/qt.prf \
/usr/share/qt4/mkspecs/features/unix/thread.prf \
/usr/share/qt4/mkspecs/features/moc.prf \
/usr/share/qt4/mkspecs/features/resources.prf \
/usr/share/qt4/mkspecs/features/uic.prf \
/usr/share/qt4/mkspecs/features/yacc.prf \
/usr/share/qt4/mkspecs/features/lex.prf \
/usr/share/qt4/mkspecs/features/include_source_dir.prf \
/usr/lib/x86_64-linux-gnu/libQtXml.prl \
/usr/lib/x86_64-linux-gnu/libQtGui.prl \
/usr/lib/x86_64-linux-gnu/libQtNetwork.prl \
/usr/lib/x86_64-linux-gnu/libQtCore.prl
$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ CONFIG+=debug CONFIG+=declarative_debug -o Makefile KonaClient.pro
/usr/share/qt4/mkspecs/common/unix.conf:
/usr/share/qt4/mkspecs/common/linux.conf:
/usr/share/qt4/mkspecs/common/gcc-base.conf:
/usr/share/qt4/mkspecs/common/gcc-base-unix.conf:
/usr/share/qt4/mkspecs/common/g++-base.conf:
/usr/share/qt4/mkspecs/common/g++-unix.conf:
/usr/share/qt4/mkspecs/qconfig.pri:
/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri:
/usr/share/qt4/mkspecs/features/qt_functions.prf:
/usr/share/qt4/mkspecs/features/qt_config.prf:
/usr/share/qt4/mkspecs/features/exclusive_builds.prf:
/usr/share/qt4/mkspecs/features/default_pre.prf:
/usr/share/qt4/mkspecs/features/debug.prf:
/usr/share/qt4/mkspecs/features/default_post.prf:
/usr/share/qt4/mkspecs/features/declarative_debug.prf:
/usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf:
/usr/share/qt4/mkspecs/features/warn_on.prf:
/usr/share/qt4/mkspecs/features/qt.prf:
/usr/share/qt4/mkspecs/features/unix/thread.prf:
/usr/share/qt4/mkspecs/features/moc.prf:
/usr/share/qt4/mkspecs/features/resources.prf:
/usr/share/qt4/mkspecs/features/uic.prf:
/usr/share/qt4/mkspecs/features/yacc.prf:
/usr/share/qt4/mkspecs/features/lex.prf:
/usr/share/qt4/mkspecs/features/include_source_dir.prf:
/usr/lib/x86_64-linux-gnu/libQtXml.prl:
/usr/lib/x86_64-linux-gnu/libQtGui.prl:
/usr/lib/x86_64-linux-gnu/libQtNetwork.prl:
/usr/lib/x86_64-linux-gnu/libQtCore.prl:
qmake: FORCE
@$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++ CONFIG+=debug CONFIG+=declarative_debug -o Makefile KonaClient.pro
dist:
@$(CHK_DIR_EXISTS) .tmp/KonaClient1.0.0 || $(MKDIR) .tmp/KonaClient1.0.0
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/KonaClient1.0.0/ && $(COPY_FILE) --parents mainwindow.h konasearch.h konaclient.h konaimage.h flowlayout.h konapreviewimageview.h konatags.h konatag.h konarelatedtags.h imageviewer.h .tmp/KonaClient1.0.0/ && $(COPY_FILE) --parents main.cpp mainwindow.cpp konasearch.cpp konaclient.cpp konaimage.cpp flowlayout.cpp konapreviewimageview.cpp konatags.cpp konatag.cpp konarelatedtags.cpp imageviewer.cpp .tmp/KonaClient1.0.0/ && $(COPY_FILE) --parents mainwindow.ui konapreviewimageview.ui imageviewer.ui .tmp/KonaClient1.0.0/ && (cd `dirname .tmp/KonaClient1.0.0` && $(TAR) KonaClient1.0.0.tar KonaClient1.0.0 && $(COMPRESS) KonaClient1.0.0.tar) && $(MOVE) `dirname .tmp/KonaClient1.0.0`/KonaClient1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/KonaClient1.0.0
clean:compiler_clean
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
####### Sub-libraries
distclean: clean
-$(DEL_FILE) $(TARGET)
-$(DEL_FILE) Makefile
check: first
mocclean: compiler_moc_header_clean compiler_moc_source_clean
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
compiler_moc_header_make_all: moc_mainwindow.cpp moc_konasearch.cpp moc_konaclient.cpp moc_konaimage.cpp moc_konapreviewimageview.cpp moc_konatags.cpp moc_konatag.cpp moc_konarelatedtags.cpp moc_imageviewer.cpp
compiler_moc_header_clean:
-$(DEL_FILE) moc_mainwindow.cpp moc_konasearch.cpp moc_konaclient.cpp moc_konaimage.cpp moc_konapreviewimageview.cpp moc_konatags.cpp moc_konatag.cpp moc_konarelatedtags.cpp moc_imageviewer.cpp
moc_mainwindow.cpp: konaclient.h \
konasearch.h \
konaimage.h \
konatags.h \
konatag.h \
konarelatedtags.h \
flowlayout.h \
imageviewer.h \
mainwindow.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) mainwindow.h -o moc_mainwindow.cpp
moc_konasearch.cpp: konaclient.h \
konaimage.h \
konasearch.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konasearch.h -o moc_konasearch.cpp
moc_konaclient.cpp: konaclient.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konaclient.h -o moc_konaclient.cpp
moc_konaimage.cpp: konaclient.h \
konaimage.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konaimage.h -o moc_konaimage.cpp
moc_konapreviewimageview.cpp: konaimage.h \
konaclient.h \
konapreviewimageview.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konapreviewimageview.h -o moc_konapreviewimageview.cpp
moc_konatags.cpp: konatag.h \
konaclient.h \
konatags.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konatags.h -o moc_konatags.cpp
moc_konatag.cpp: konatag.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konatag.h -o moc_konatag.cpp
moc_konarelatedtags.cpp: konaclient.h \
konatag.h \
konarelatedtags.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) konarelatedtags.h -o moc_konarelatedtags.cpp
moc_imageviewer.cpp: konaimage.h \
konaclient.h \
imageviewer.h
/usr/bin/moc-qt4 $(DEFINES) $(INCPATH) imageviewer.h -o moc_imageviewer.cpp
compiler_rcc_make_all:
compiler_rcc_clean:
compiler_image_collection_make_all: qmake_image_collection.cpp
compiler_image_collection_clean:
-$(DEL_FILE) qmake_image_collection.cpp
compiler_moc_source_make_all:
compiler_moc_source_clean:
compiler_uic_make_all: ui_mainwindow.h ui_konapreviewimageview.h ui_imageviewer.h
compiler_uic_clean:
-$(DEL_FILE) ui_mainwindow.h ui_konapreviewimageview.h ui_imageviewer.h
ui_mainwindow.h: mainwindow.ui
/usr/bin/uic-qt4 mainwindow.ui -o ui_mainwindow.h
ui_konapreviewimageview.h: konapreviewimageview.ui
/usr/bin/uic-qt4 konapreviewimageview.ui -o ui_konapreviewimageview.h
ui_imageviewer.h: imageviewer.ui
/usr/bin/uic-qt4 imageviewer.ui -o ui_imageviewer.h
compiler_yacc_decl_make_all:
compiler_yacc_decl_clean:
compiler_yacc_impl_make_all:
compiler_yacc_impl_clean:
compiler_lex_make_all:
compiler_lex_clean:
compiler_clean: compiler_moc_header_clean compiler_uic_clean
####### Compile
main.o: main.cpp mainwindow.h \
konaclient.h \
konasearch.h \
konaimage.h \
konatags.h \
konatag.h \
konarelatedtags.h \
flowlayout.h \
imageviewer.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp
mainwindow.o: mainwindow.cpp mainwindow.h \
konaclient.h \
konasearch.h \
konaimage.h \
konatags.h \
konatag.h \
konarelatedtags.h \
flowlayout.h \
imageviewer.h \
ui_mainwindow.h \
konapreviewimageview.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o mainwindow.o mainwindow.cpp
konasearch.o: konasearch.cpp konasearch.h \
konaclient.h \
konaimage.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konasearch.o konasearch.cpp
konaclient.o: konaclient.cpp konaclient.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konaclient.o konaclient.cpp
konaimage.o: konaimage.cpp konaimage.h \
konaclient.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konaimage.o konaimage.cpp
flowlayout.o: flowlayout.cpp flowlayout.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o flowlayout.o flowlayout.cpp
konapreviewimageview.o: konapreviewimageview.cpp konapreviewimageview.h \
konaimage.h \
konaclient.h \
ui_konapreviewimageview.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konapreviewimageview.o konapreviewimageview.cpp
konatags.o: konatags.cpp konatags.h \
konatag.h \
konaclient.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konatags.o konatags.cpp
konatag.o: konatag.cpp konatag.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konatag.o konatag.cpp
konarelatedtags.o: konarelatedtags.cpp konarelatedtags.h \
konaclient.h \
konatag.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o konarelatedtags.o konarelatedtags.cpp
imageviewer.o: imageviewer.cpp imageviewer.h \
konaimage.h \
konaclient.h \
ui_imageviewer.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o imageviewer.o imageviewer.cpp
moc_mainwindow.o: moc_mainwindow.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_mainwindow.o moc_mainwindow.cpp
moc_konasearch.o: moc_konasearch.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konasearch.o moc_konasearch.cpp
moc_konaclient.o: moc_konaclient.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konaclient.o moc_konaclient.cpp
moc_konaimage.o: moc_konaimage.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konaimage.o moc_konaimage.cpp
moc_konapreviewimageview.o: moc_konapreviewimageview.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konapreviewimageview.o moc_konapreviewimageview.cpp
moc_konatags.o: moc_konatags.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konatags.o moc_konatags.cpp
moc_konatag.o: moc_konatag.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konatag.o moc_konatag.cpp
moc_konarelatedtags.o: moc_konarelatedtags.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_konarelatedtags.o moc_konarelatedtags.cpp
moc_imageviewer.o: moc_imageviewer.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_imageviewer.o moc_imageviewer.cpp
####### Install
install: FORCE
uninstall: FORCE
FORCE:

195
flowlayout.cpp Executable file
View File

@ -0,0 +1,195 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui>
#include "flowlayout.h"
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
int FlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
else
return 0;
}
Qt::Orientations FlowLayout::expandingDirections() const
{
return 0;
}
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin());
return size;
}
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
QLayoutItem *item;
foreach (item, itemList) {
QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
return y + lineHeight - rect.y() + bottom;
}
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
}
void FlowLayout::insertWidgetAt(QWidget *widget, int index)
{
addWidget(widget);
this->itemList.move(this->itemList.count()-1, 0);
//this->itemList.insert(index, new QWidgetItem(widget));
}

77
flowlayout.h Executable file
View File

@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QLayout>
#include <QRect>
#include <QWidgetItem>
class FlowLayout : public QLayout
{
public:
FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item);
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const;
bool hasHeightForWidth() const;
int heightForWidth(int) const;
int count() const;
QLayoutItem *itemAt(int index) const;
QSize minimumSize() const;
void setGeometry(const QRect &rect);
QSize sizeHint() const;
QLayoutItem *takeAt(int index);
void insertWidgetAt(QWidget *widget, int index);
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};
#endif

200
imageviewer.cpp Executable file
View File

@ -0,0 +1,200 @@
#include "imageviewer.h"
#include "ui_imageviewer.h"
#include <QWheelEvent>
#include <QDebug>
ImageViewer::ImageViewer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ImageViewer)
{
ui->setupUi(this);
EventFilterizer* interceptor = new EventFilterizer;
ui->centralwidget->installEventFilter(interceptor);
connect(interceptor, SIGNAL(onMove(int,int)),
this, SLOT(move(int,int)));
connect(interceptor, SIGNAL(onZoom(int)),
this, SLOT(zoom(int)));
}
ImageViewer::~ImageViewer()
{
delete ui;
}
void ImageViewer::setImage(KonaImage *Ki) { // TODO: (no todo but a notice: This function requires the image to be available locally when called!)
//ki = Ki; //TODO: <--
disconnect(Ki, SIGNAL(imageDownloaded(KonaImage*,QString)),
this, SLOT(setImage(KonaImage*)));
currentID = Ki->getId();
pix.load(Ki->getLocalImagePath());
// We're doing this a bit complicated. (It's to remove any frame from the label)
QPixmap temp = pix.scaled(this->width(), this->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
ui->imgLabel->setGeometry(0,0,this->width(), this->height());
ui->imgLabel->setPixmap(temp);
ui->imgLabel->setGeometry((ui->imgLabel->width()-temp.width()) / 2,
(ui->imgLabel->height()-temp.height()) / 2,
temp.width(), temp.height());
setWindowTitle(tr("KonaClient - Image viewer: %1 (%2x%3)").arg(QString::number(Ki->getId()),QString::number(Ki->getWidth()),QString::number(Ki->getHeight())));
}
void ImageViewer::showLoading() {
ui->imgLabel->setText("Loading image...");
setWindowTitle(tr("KonaClient - Image viewer"));
ui->imgLabel->setGeometry(0,0,this->width(),this->height());
}
void ImageViewer::move(int dx, int dy) {
ui->imgLabel->setGeometry(ui->imgLabel->x() + dx, ui->imgLabel->y() + dy, ui->imgLabel->width(),ui->imgLabel->height());
checkPos();
}
void ImageViewer::zoom(int mode) {
if (mode == ZOOM_OUT) {
ui->imgLabel->setGeometry(ui->imgLabel->x() + (pix.width()/20)/2,
ui->imgLabel->y() + (pix.height()/20)/2,
ui->imgLabel->width() - pix.width()/20,
ui->imgLabel->height() - pix.height()/20);
}
else if (mode == ZOOM_IN) {
ui->imgLabel->setGeometry(ui->imgLabel->x() - (pix.width()/20)/2,
ui->imgLabel->y() - (pix.height()/20)/2,
ui->imgLabel->width() + pix.width()/20,
ui->imgLabel->height() + pix.height()/20);
}
checkPos();
ui->imgLabel->setPixmap(pix.scaled(ui->imgLabel->width(), ui->imgLabel->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
void ImageViewer::checkPos() {
if (ui->imgLabel->width() < this->width()) {
if (ui->imgLabel->x() < 0) {
ui->imgLabel->setGeometry(0,
ui->imgLabel->y(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
else if (ui->imgLabel->x() + ui->imgLabel->width() > this->width()) {
ui->imgLabel->setGeometry(this->width() - ui->imgLabel->width(),
ui->imgLabel->y(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
}
else {
// if (ui->imgLabel->x() )
}
if (ui->imgLabel->height() < this->height()) {
if (ui->imgLabel->y() < 0) {
ui->imgLabel->setGeometry(ui->imgLabel->x(),
0,
ui->imgLabel->width(),
ui->imgLabel->height());
}
else if (ui->imgLabel->y() + ui->imgLabel->height() > this->height()) {
ui->imgLabel->setGeometry(ui->imgLabel->x(),
this->height() - ui->imgLabel->height(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
}
else {
if (ui->imgLabel->y() + ui->imgLabel->height() < this->height()) {
ui->imgLabel->setGeometry(ui->imgLabel->x(),
this->height() - ui->imgLabel->height(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
else if (ui->imgLabel->y() > 0) {
ui->imgLabel->setGeometry(ui->imgLabel->x(),
0,
ui->imgLabel->width(),
ui->imgLabel->height());
}
if (ui->imgLabel->x() + ui->imgLabel->width() < this->width()) {
ui->imgLabel->setGeometry(this->width() - ui->imgLabel->width(),
ui->imgLabel->y(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
else if (ui->imgLabel->x() > 0) {
ui->imgLabel->setGeometry(0,
ui->imgLabel->y(),
ui->imgLabel->width(),
ui->imgLabel->height());
}
}
}
void ImageViewer::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Shift) {
emit loadPrev();
}
else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_Return || e->key() == Qt::Key_Control) {
emit loadNext();
}
}
// MOUSE EVENT
EventFilterizer::EventFilterizer(QObject *parent) :
QObject(parent)
{
}
bool EventFilterizer::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::Wheel) {
QWheelEvent *wheelEvent = static_cast< QWheelEvent * >( event );
if (wheelEvent->delta() > 0) {
emit onZoom(ZOOM_IN);
}
else if (wheelEvent->delta() < 0) {
emit onZoom(ZOOM_OUT);
}
return true;
}
else if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast< QMouseEvent * >( event );
lastX = mouseEvent->x();
lastY = mouseEvent->y();
return true;
}
else if (event->type() == QEvent::MouseMove) { // ONLY CALLED WHEN PRESSED
//qDebug() << "MOVE";
QMouseEvent *mouseEvent = static_cast< QMouseEvent * >( event );
emit onMove(mouseEvent->x() - lastX,
mouseEvent->y() - lastY);
lastX = mouseEvent->x();
lastY = mouseEvent->y();
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}

71
imageviewer.h Executable file
View File

@ -0,0 +1,71 @@
#ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H
#include <QMainWindow>
#include "konaimage.h"
#include <QDebug>
namespace Ui {
class ImageViewer;
}
class ImageViewer : public QMainWindow
{
Q_OBJECT
#define ZOOM_IN 1
#define ZOOM_OUT 2
public:
explicit ImageViewer(QWidget *parent = 0);
~ImageViewer();
void showLoading();
//void mouseMoveEvent(QMouseEvent *e);
void keyPressEvent(QKeyEvent* e);
int getCurrentId() {return currentID;}
private:
QPixmap pix;
int currentID;
public slots:
void setImage(KonaImage *Ki);
void move(int dx, int dy);
void zoom(int mode);
void checkPos();
signals:
void loadPrev();
void loadNext();
private:
Ui::ImageViewer *ui;
};
class EventFilterizer : public QObject
{
Q_OBJECT
public:
explicit EventFilterizer(QObject *parent = 0);
void setIv(ImageViewer *Iv) {iv = Iv;}
private:
ImageViewer *iv;
int lastX;
int lastY;
protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void onMove(int, int);
void onZoom(int);
public slots:
};
#endif // IMAGEVIEWER_H

58
imageviewer.ui Executable file
View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImageViewer</class>
<widget class="QMainWindow" name="ImageViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="windowTitle">
<string>KonaChan - Image viewer</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: black;</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="imgLabel">
<property name="geometry">
<rect>
<x>80</x>
<y>70</y>
<width>640</width>
<height>480</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Loading image...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections/>
<slots>
<slot>onResize()</slot>
</slots>
</ui>

46
konaclient.cpp Executable file
View File

@ -0,0 +1,46 @@
#include "konaclient.h"
KonaClient::KonaClient(QString TempDir, QString CacheDir, QString ArchiveDir, QString Server)
{
// Copy info to RAM
tempDir = TempDir;
cacheDir = CacheDir;
archiveDir = ArchiveDir;
server = Server;
// Create all directories
QDir aD(archiveDir);
if (!aD.exists()) aD.mkpath(archiveDir);
QDir cD(cacheDir);
if (!cD.exists()) cD.mkpath(cacheDir);
QDir tD(tempDir);
if (!tD.exists()) tD.mkpath(tempDir);
}
KonaClient::~KonaClient()
{
// Remove temp dir
QDir tD(tempDir);
if (tD.exists()) removeDir(tempDir);
}
// Copied from http://www.qtcentre.org/threads/4166-remove-directory-empty-or-not-empty
// Removes all files and subdirectories of a specific directory.
void KonaClient::removeDir(const QString &path)
{
QFileInfo fileInfo(path);
if(fileInfo.isDir()){
QDir dir(path);
QStringList fileList = dir.entryList();
for(int i = 0; i < fileList.count(); ++i){
QFile::remove(fileList.at(i));
}
dir.rmdir(path);
}
else{
QFile::remove(path);
}
}

50
konaclient.h Executable file
View File

@ -0,0 +1,50 @@
#ifndef KONACLIENT_H
#define KONACLIENT_H
#include <QObject>
#include <QDir>
// ERROR CODES
#define ERROR_TAGS_TEMPFILE 1
#define ERROR_TAGS_FORMAT 2
#define ERROR_SEARCH_TEMPFILE 1
#define ERROR_SEARCH_FORMAT 2
#define ERROR_SEARCH_XML 3
#define ERROR_SEARCH_HTTP 4
// Windows-Compatibility
#ifdef _WIN32
#define SLASH "\\"
#else
#define SLASH "/"
#endif
class KonaClient : public QObject
{
Q_OBJECT
public:
KonaClient(QString TempDir, QString CacheDir, QString ArchiveDir, QString Server = "konachan.com");
~KonaClient();
QString getTempDir() {return tempDir;}
QString getCacheDir() {return cacheDir;}
QString getArchiveDir() {return archiveDir;}
QString getServer() {return server;}
private:
QString tempDir;
QString cacheDir;
QString archiveDir;
QString server;
void removeDir(const QString &path);
};
#endif // KONACLIENT_H

208
konaimage.cpp Executable file
View File

@ -0,0 +1,208 @@
#include "konaimage.h"
#include <QDebug>
KonaImage::KonaImage(KonaClient *Kc, int Id, QStringList Tags, int CreatedAt, int CreatorId, QString Author, int Change, QString Source, int Score, QString Md5, int FileSize, QString FileUrl, bool IsShownInIndex, QString PreviewUrl, int PreviewWidth, int PreviewHeight, int ActualPreviewWidth, int ActualPreviewHeight, QString SampleUrl, int SampleWidth, int SampleHeight, int SampleFileSize, QString JpegUrl, int JpegWidth, int JpegHeight, int JpegFileSize, QString Rating, bool HasChildren, int ParentID, QString Status, int Width, int Height, bool IsHeld, QString FramesPendingString, QString FramesString)
{
// Reset
previewStatusCode = 1;
imageStatusCode = 1;
jpegStatusCode = 1;
sampleStatusCode = 1;
// Copy to RAM
kc = Kc;
id = Id;
tags = Tags;
createdAt = CreatedAt;
creatorId = CreatorId;
author = Author;
change = Change;
source = Source;
score = Score;
md5 = Md5;
fileSize = FileSize;
fileUrl = FileUrl;
isShownInIndex = IsShownInIndex;
previewUrl = PreviewUrl;
previewWidth = PreviewWidth;
previewHeight = PreviewHeight;
actualPreviewWidth = ActualPreviewWidth;
actualPreviewHeight = ActualPreviewHeight;
sampleUrl = SampleUrl;
sampleWidth = SampleWidth;
sampleHeight = SampleHeight;
sampleFileSize = SampleFileSize;
jpegUrl = JpegUrl;
jpegWidth = JpegWidth;
jpegHeight = JpegHeight;
jpegFileSize = JpegFileSize;
rating = Rating;
hasChildren = HasChildren;
parentID = ParentID;
status = Status;
width = Width;
height = Height;
isHeld = IsHeld;
framesPendingString = FramesPendingString;
framesString = FramesString;
// Initialize preview file
previewFile = new QFile();
previewFile->setFileName(KONAIMAGE_PREVIEWPATH);
// Prepare preview HTTP
previewHttp = new QHttp("konachan.com"); //TODO: all these konachans.com should be Kc->getServer()
connect(previewHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(previewResponseHeaderReceived(QHttpResponseHeader)));
connect(previewHttp, SIGNAL(requestFinished(int,bool)),
this, SLOT(previewRequestFinished()));
// Initialize image file (highres)
imageFile = new QFile();
imageFile->setFileName(KONAIMAGE_LOCALPATH);
// Prepare image HTTP
imageHttp = new QHttp("konachan.com");
connect(imageHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(imageResponseHeaderReceived(QHttpResponseHeader)));
connect(imageHttp, SIGNAL(requestFinished(int,bool)),
this, SLOT(imageRequestFinished()));
// Initialize jpeg file
jpegFile = new QFile();
jpegFile->setFileName(KONAIMAGE_JPEGPATH);
// Prepare jpeg HTTP
jpegHttp = new QHttp("konachan.com");
connect(jpegHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(jpegResponseHeaderReceived(QHttpResponseHeader)));
connect(jpegHttp, SIGNAL(requestFinished(int,bool)),
this, SLOT(jpegRequestFinished()));
// Initialize sample file
sampleFile = new QFile();
sampleFile->setFileName(KONAIMAGE_SAMPLEPATH);
// Prepare sample HTTP
sampleHttp = new QHttp("konachan.com");
connect(sampleHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(sampleResponseHeaderReceived(QHttpResponseHeader)));
connect(sampleHttp, SIGNAL(requestFinished(int,bool)),
this, SLOT(sampleRequestFinished()));
}
void KonaImage::DownloadPreview(bool overwrite) {
if (previewStatusCode != 1) return; // Already in progress
if (!previewFile->exists() || overwrite) {
previewFile->open(QFile::ReadWrite);
previewStatusCode = 0;
previewHttp->get(previewUrl, previewFile);
}
else if (previewFile->exists()) {
previewStatusCode = 200; // Fake HTTP OK
previewRequestFinished();
}
}
void KonaImage::previewRequestFinished() {
//qDebug() << "PREVIEW FINISHED WITH HTTP " << previewStatusCode;
previewFile->close();
if (previewStatusCode == 200) previewStatusCode = 1;
emit previewDownloaded(this, previewFile->fileName());
}
void KonaImage::previewResponseHeaderReceived(QHttpResponseHeader resp) {
previewStatusCode = resp.statusCode();
}
// "real" image
void KonaImage::DownloadImage(bool overwrite) {
qDebug() << "Download request of real image: " << this->id;
if (imageStatusCode != 1) return; // Already in progress
if (!imageFile->exists() || overwrite) {
imageFile->open(QFile::ReadWrite);
imageStatusCode = 0;
imageHttp->get(fileUrl, imageFile);
}
else if (imageFile->exists()) {
imageFile->open(QFile::ReadWrite);
QCryptographicHash md5sum(QCryptographicHash::Md5);
md5sum.addData(imageFile->readAll());
imageFile->reset();
if (md5sum.result().toHex() == md5) {
imageStatusCode = 200; // Fake HTTP OK
imageRequestFinished();
}
else {
qDebug() << "ERROR: KonaImage: MD5 checksum verification failed!";
imageStatusCode = 0;
imageHttp->get(fileUrl, imageFile);
}
}
}
void KonaImage::imageRequestFinished() {
imageFile->close();
if (imageStatusCode == 200) imageStatusCode = 1;
emit imageDownloaded(this, imageFile->fileName());
}
void KonaImage::imageResponseHeaderReceived(QHttpResponseHeader resp) {
imageStatusCode = resp.statusCode();
}
// jpeg image
void KonaImage::DownloadJpeg(bool overwrite) {
if (jpegStatusCode != 1) return; // Already in progress
if (!jpegFile->exists() || overwrite) {
jpegFile->open(QFile::ReadWrite);
jpegStatusCode = 0;
jpegHttp->get(jpegUrl, jpegFile);
}
else if (jpegFile->exists()) {
jpegStatusCode = 200; // Fake HTTP OK
jpegRequestFinished();
}
}
void KonaImage::jpegRequestFinished() {
//qDebug() << "Jpeg FINISHED WITH HTTP " << JpegStatusCode;
jpegFile->close();
if (jpegStatusCode == 200) jpegStatusCode = 1;
emit jpegDownloaded(this, jpegFile->fileName());
}
void KonaImage::jpegResponseHeaderReceived(QHttpResponseHeader resp) {
jpegStatusCode = resp.statusCode();
}
// sample image
void KonaImage::DownloadSample(bool overwrite) {
if (sampleStatusCode != 1) return; // Already in progress
if (!sampleFile->exists() || overwrite) {
sampleFile->open(QFile::ReadWrite);
sampleStatusCode = 0;
sampleHttp->get(sampleUrl, sampleFile);
}
else if (sampleFile->exists()) {
sampleStatusCode = 200; // Fake HTTP OK
sampleRequestFinished();
}
}
void KonaImage::sampleRequestFinished() {
//qDebug() << "sample FINISHED WITH HTTP " << sampleStatusCode;
sampleFile->close();
if (sampleStatusCode == 200) sampleStatusCode = 1;
emit sampleDownloaded(this, sampleFile->fileName());
}
void KonaImage::sampleResponseHeaderReceived(QHttpResponseHeader resp) {
sampleStatusCode = resp.statusCode();
}

118
konaimage.h Executable file
View File

@ -0,0 +1,118 @@
#ifndef KONAIMAGE_H
#define KONAIMAGE_H
#include <QObject>
#include <QStringList>
#include <QHttp>
#include <QFile>
#include <QCryptographicHash>
#include "konaclient.h"
#define KONAIMAGE_PREVIEWPATH kc->getCacheDir() + SLASH + "preview_" + QString::number(id) + ".jpg"
#define KONAIMAGE_LOCALPATH kc->getArchiveDir() + SLASH + QString::number(id) + fileUrl.right(4)
#define KONAIMAGE_JPEGPATH kc->getCacheDir() + SLASH + "jpeg_" + QString::number(id) + ".jpg"
#define KONAIMAGE_SAMPLEPATH kc->getCacheDir() + SLASH + "sample_" + QString::number(id) + sampleUrl.right(4)
class KonaImage : public QObject
{
Q_OBJECT
public:
KonaImage(KonaClient *kc, int Id, QStringList Tags, int CreatedAt, int CreatorId, QString Author, int Change, QString Source, int Score, QString Md5, int FileSize, QString FileUrl, bool IsShownInIndex, QString PreviewUrl, int PreviewWidth, int PreviewHeight, int ActualPreviewWidth, int ActualPreviewHeight, QString SampleUrl, int SampleWidth, int SampleHeight, int SampleFileSize, QString JpegUrl, int JpegWidth, int JpegHeight, int JpegFileSize, QString Rating, bool HasChildren, int ParentID, QString Status, int Width, int Height, bool IsHeld, QString FramesPendingString, QString FramesString);
int getId() {return id;}
int getWidth() {return width;}
int getHeight() {return height;}
QString getLocalPreviewPath() {return KONAIMAGE_PREVIEWPATH;}
QString getLocalImagePath() {return KONAIMAGE_LOCALPATH;}
QString getLocalJpegPath() {return KONAIMAGE_JPEGPATH;}
QString getLocalSamplePath() {return KONAIMAGE_SAMPLEPATH;}
private:
KonaClient *kc;
int id;
QStringList tags;
int createdAt;
int creatorId;
QString author;
int change;
QString source;
int score;
QString md5;
int fileSize;
QString fileUrl;
bool isShownInIndex;
QString previewUrl;
int previewWidth;
int previewHeight;
int actualPreviewWidth;
int actualPreviewHeight;
QString sampleUrl;
int sampleWidth;
int sampleHeight;
int sampleFileSize;
QString jpegUrl;
int jpegWidth;
int jpegHeight;
int jpegFileSize;
QString rating;
bool hasChildren;
int parentID;
QString status;
int width;
int height;
bool isHeld;
QString framesPendingString;
QString framesString;
// Eventuell fehlen noch children
// Preview image
QHttp *previewHttp;
QFile *previewFile;
int previewStatusCode;
// "real" image
QHttp *imageHttp;
QFile *imageFile;
int imageStatusCode;
// jpeg image
QHttp *jpegHttp;
QFile *jpegFile;
int jpegStatusCode;
// sample image
QHttp *sampleHttp;
QFile *sampleFile;
int sampleStatusCode;
signals:
void previewDownloaded(KonaImage *ki, QString localPath);
void imageDownloaded(KonaImage *ki, QString localPath);
void jpegDownloaded(KonaImage *ki, QString localPath);
void sampleDownloaded(KonaImage *ki, QString localPath);
public slots:
void previewRequestFinished();
void previewResponseHeaderReceived(QHttpResponseHeader resp);
void imageRequestFinished();
void imageResponseHeaderReceived(QHttpResponseHeader resp);
void jpegRequestFinished();
void jpegResponseHeaderReceived(QHttpResponseHeader resp);
void sampleRequestFinished();
void sampleResponseHeaderReceived(QHttpResponseHeader resp);
void DownloadPreview(bool overwrite = false);
void DownloadImage(bool overwrite = false);
void DownloadJpeg(bool overwrite = false);
void DownloadSample(bool overwrite = false);
};
#endif // KONAIMAGE_H

56
konapreviewimageview.cpp Executable file
View File

@ -0,0 +1,56 @@
#include "konapreviewimageview.h"
#include "ui_konapreviewimageview.h"
#include <QDebug>
KonaPreviewImageView::KonaPreviewImageView(QWidget *parent) :
QWidget(parent),
ui(new Ui::KonaPreviewImageView)
{
ui->setupUi(this);
ui->imgLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
// ui->imgLabel->setPixmap(QPixmap ("/home/markus/Bilder/temp.jpg"));
imgReloadCounter = 0;
}
KonaPreviewImageView::~KonaPreviewImageView()
{
delete ui;
}
void KonaPreviewImageView::OpenImage()
{
emit imageClicked(ki);
}
void KonaPreviewImageView::RMB() {
qDebug() << "RMB";
}
void KonaPreviewImageView::downloadImage()
{
emit buttonClicked(ki);
}
void KonaPreviewImageView::previewDownloaded(KonaImage *Ki, QString localPath) {
ki = Ki;
QPixmap pix (localPath);
if (pix.width() > 0) {
pix = pix.scaled(200,150, Qt::KeepAspectRatio, Qt::SmoothTransformation);
ui->imgLabel->setPixmap(pix);
}
else {
imgReloadCounter++;
if (imgReloadCounter < 3) {
qDebug() << "ERROR: KonaPreviewImageView: Corrupt image. Reload #" << imgReloadCounter;
ki->DownloadPreview(true);
}
}
}
void KonaPreviewImageView::setCaption(QString text) {
ui->btnResolution->setText(text);
}

39
konapreviewimageview.h Executable file
View File

@ -0,0 +1,39 @@
#ifndef KONAPREVIEWIMAGEVIEW_H
#define KONAPREVIEWIMAGEVIEW_H
#include <QWidget>
#include "konaimage.h"
namespace Ui {
class KonaPreviewImageView;
}
class KonaPreviewImageView : public QWidget
{
Q_OBJECT
public:
explicit KonaPreviewImageView(QWidget *parent = 0);
~KonaPreviewImageView();
KonaImage* getKonaImage() {return ki;}
private:
KonaImage *ki;
int imgReloadCounter;
public slots:
void OpenImage();
void previewDownloaded(KonaImage *Ki, QString localPath);
void setCaption(QString text);
void RMB();
void downloadImage();
signals:
void imageClicked(KonaImage*);
void buttonClicked(KonaImage*);
private:
Ui::KonaPreviewImageView *ui;
};
#endif // KONAPREVIEWIMAGEVIEW_H

133
konapreviewimageview.ui Executable file
View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KonaPreviewImageView</class>
<widget class="QWidget" name="KonaPreviewImageView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>170</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>170</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">background: rgb(0, 0, 0);</string>
</property>
<widget class="QPushButton" name="btnResolution">
<property name="geometry">
<rect>
<x>2</x>
<y>152</y>
<width>196</width>
<height>16</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true">color: #333;
border: 1px solid #555;
background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 #888);</string>
</property>
<property name="text">
<string>0000 x 0000</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="imgLabel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>150</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="btnImage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>150</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">border: none;
background: none;
</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>btnResolution</sender>
<signal>clicked()</signal>
<receiver>KonaPreviewImageView</receiver>
<slot>downloadImage()</slot>
<hints>
<hint type="sourcelabel">
<x>34</x>
<y>157</y>
</hint>
<hint type="destinationlabel">
<x>40</x>
<y>150</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnImage</sender>
<signal>clicked()</signal>
<receiver>KonaPreviewImageView</receiver>
<slot>OpenImage()</slot>
<hints>
<hint type="sourcelabel">
<x>134</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>184</x>
<y>151</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>OpenImage()</slot>
<slot>RMB()</slot>
<slot>downloadImage()</slot>
</slots>
</ui>

116
konarelatedtags.cpp Executable file
View File

@ -0,0 +1,116 @@
#include "konarelatedtags.h"
#include <QDebug>
KonaRelatedTags::KonaRelatedTags(KonaClient *Kc, QString Tags, QString Type)
{
kc = Kc;
tags = Tags;
type = Type;
// Initialize temp file
int fileID = 0;
file = new QFile(kc->getTempDir() + SLASH + "relTags_0");
while (file->exists()) {
fileID++;
file->setFileName(kc->getTempDir() + SLASH + "relTags_" + QString::number(fileID));
}
// Prepare HTTP
http = new QHttp(kc->getServer());
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
connect(http, SIGNAL(requestFinished(int,bool)),
this, SLOT(requestFinished()));
// Search
if (Tags == "") {
searchIsDone = true;
}
else {
searchAgain();
}
}
void KonaRelatedTags::newSearch(QString Tags, QString Type)
{
if (Tags != "__KEEPOLD__") tags = Tags;
if (Type != "__KEEPOLD__") type = Type;
searchAgain();
}
void KonaRelatedTags::searchAgain() {
result.clear();
searchIsDone = false;
statusCode = 0;
if (!file->open(QIODevice::ReadWrite)) {
qDebug() << "KonaRelatedTags: ERROR: Can't open temp file for search!";
emit searchFailed(this, ERROR_TAGS_TEMPFILE);
return;
}
QUrl url("/tag/related.xml?tags=" + tags + (type != "" ? "&type=" + type : ""));
qDebug() << url.toString();
http->get(url.toString(), file);
}
void KonaRelatedTags::requestFinished() {
if (statusCode == 200) {
file->flush();
file->reset();
QDomDocument doc ("search");
if (!doc.setContent(file)) {
qDebug() << "KonaRelatedTags: ERROR: Can't parse xml!";
emit searchFailed(this, ERROR_SEARCH_XML);
file->close();
file->remove();
return;
}
file->close();
file->remove(); // We don't need it anymore
QDomElement root = doc.documentElement();
if (root.tagName() != "tags") {
qDebug() << "KonaRelatedTags: ERROR: Wrong root element!";
emit searchFailed(this, ERROR_TAGS_FORMAT);
return;
}
QDomElement el = root.elementsByTagName("tag").at(1).toElement();
if (el.isNull()) {
qDebug() << "KonaRelatedTags: ERROR: Couldn't get first element!";
emit searchFailed(this, ERROR_TAGS_FORMAT);
return;
}
#define toBool(a) (a == "true" ? true : false)
int x = 1;
while (!el.isNull()) { //TODO: Filter doubles
result.append(new KonaTag(el.attribute("id", "0").toInt(),
el.attribute("name", ""),
el.attribute("count", "0").toInt(),
el.attribute("type", "unknown").toInt(),
toBool(el.attribute("ambiguous", "false"))));
x++;
el = root.elementsByTagName("tag").at(x).toElement();
}
qDebug() << "KonaRelatedTags: Search finished!";
searchIsDone = true;
emit searchFinished(this);
}
else {
qDebug() << "KonaRelatedTags: ERROR: " << "Received HTTP error code: " << statusCode;
emit searchFailed(this, ERROR_SEARCH_HTTP);
}
}
void KonaRelatedTags::responseHeaderReceived(QHttpResponseHeader resp) {
statusCode = resp.statusCode();
}

48
konarelatedtags.h Executable file
View File

@ -0,0 +1,48 @@
#ifndef KONARELATEDTAGS_H
#define KONARELATEDTAGS_H
#include <QObject>
#include "konaclient.h"
#include <QHttp>
#include <QFile>
#include <QtXml>
#include "konatag.h"
class KonaRelatedTags : public QObject
{
Q_OBJECT
public:
KonaRelatedTags(KonaClient *Kc, QString Tags, QString Type);
QString getSourceTags() {return tags;}
QString getType() {return type;}
QList<KonaTag*> getTags() {return result;}
void newSearch(QString Tags = "__KEEPOLD__", QString Type = "__KEEPOLD__");
void searchAgain();
private:
KonaClient *kc;
QString tags;
QString type;
QHttp *http;
QFile *file;
int statusCode;
int searchIsDone;
QList<KonaTag*> result;
signals:
void searchFinished(KonaRelatedTags *krt);
void searchFailed(KonaRelatedTags *krt, int errorCode);
public slots:
void requestFinished();
void responseHeaderReceived(QHttpResponseHeader resp);
};
#endif // KONARELATEDTAGS_H

195
konasearch.cpp Executable file
View File

@ -0,0 +1,195 @@
#include "konasearch.h"
#include <QDebug>
#include <QtXml/QDomDocument>
KonaSearch::KonaSearch(KonaClient *Kc, QString Tags, int Page, int Limit)
{
// Reset
searchIsDone = false;
// Copy search info to RAM
kc = Kc;
tags = Tags;
page = Page;
if (Limit < 100) {
limit = Limit;
}
else {
limit = 100;
}
// Initialize temp file
int fileID = 0;
file = new QFile(kc->getTempDir() + SLASH + "search_0");
while (file->exists()) {
fileID++;
file->setFileName(kc->getTempDir() + SLASH + "search_" + QString::number(fileID));
}
// Prepare HTTP
http = new QHttp(kc->getServer());
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
connect(http, SIGNAL(requestFinished(int,bool)),
this, SLOT(requestFinished()));
// Search
if (limit == 0) {
searchIsDone = true;
file->close();
}
else {
searchAgain();
}
}
KonaSearch::~KonaSearch()
{
file->close();
file->remove();
file->deleteLater();
http->closeConnection();
http->close();
http->deleteLater();
}
void KonaSearch::newSearch(QString Tags, int Page, int Limit) {
// Reset
searchIsDone = false;
result.clear();
// Update search info to RAM
tags = Tags;
page = Page;
if (Limit < 100) {
limit = Limit;
}
else {
limit = 100;
}
file->close();
file->remove();
file->open(QFile::ReadWrite);
searchAgain();
}
void KonaSearch::searchAgain()
{
searchIsDone = false;
file->close();
statusCode = 0;
if (!file->open(QIODevice::ReadWrite)) {
qDebug() << "KonaSearch: ERROR: Can't open temp file for search!";
emit searchFailed(this, ERROR_SEARCH_TEMPFILE);
return;
}
QUrl url("/post/index.xml?limit=" + QString::number(limit) + "&page=" + QString::number(page) + "&tags=" + tags);
http->get(url.toString(), file);
}
void KonaSearch::requestFinished() {
if (statusCode == 200) {
file->flush();
file->reset();
QDomDocument doc ("search");
if (!doc.setContent(file)) {
qDebug() << "KonaSearch: ERROR: Can't parse xml!";
searchIsDone = true;
emit searchFailed(this, ERROR_SEARCH_XML);
file->close();
file->remove();
return;
}
file->close();
file->remove(); // We don't need it anymore
QDomElement root = doc.documentElement();
if (root.tagName() != "posts") {
qDebug() << "KonaSearch: ERROR: Wrong root element!";
searchIsDone = true;
emit searchFailed(this, ERROR_SEARCH_FORMAT);
return;
}
QDomElement el = root.firstChildElement("post");
if (el.isNull()) {
qDebug() << "KonaSearch: ERROR: Couldn't get first element!";
searchIsDone = true;
emit searchFailed(this, ERROR_SEARCH_FORMAT);
return;
}
totalImages = root.attribute("count","-1").toInt();
offset = root.attribute("offset","-1").toInt();
#define toBool(a) (a == "true" ? true : false)
int x = 0;
while (!el.isNull()) {
QStringList Tags = el.attribute("tags", "").split(" ");
result.append(new KonaImage(kc,
el.attribute("id", "-1").toInt(),
Tags,
el.attribute("created_at", "-1").toInt(),
el.attribute("creator_id", "-1").toInt(),
el.attribute("author", ""),
el.attribute("change","-1").toInt(),
el.attribute("source", ""),
el.attribute("score", "-1").toInt(),
el.attribute("md5"),
el.attribute("file_size", "-1").toInt(),
el.attribute("file_url", ""),
toBool(el.attribute("is_shown_in_index", "")),
el.attribute("preview_url", ""),
el.attribute("preview_width", "-1").toInt(),
el.attribute("preview_height", "-1").toInt(),
el.attribute("actual_preview_width", "-1").toInt(),
el.attribute("actual_preview_height", "-1").toInt(),
el.attribute("sample_url", ""),
el.attribute("sample_width", "-1").toInt(),
el.attribute("sample_height", "-1").toInt(),
el.attribute("sample_file_size", "-1").toInt(),
el.attribute("jpeg_url", ""),
el.attribute("jpeg_width", "-1").toInt(),
el.attribute("jpeg_height", "-1").toInt(),
el.attribute("jpeg_file_size", "-1").toInt(),
el.attribute("rating", ""),
el.attribute("has_children", "").toInt(),
el.attribute("parent_id", "-1").toInt(),
el.attribute("status", ""),
el.attribute("width", "-1").toInt(),
el.attribute("height", "-1").toInt(),
toBool(el.attribute("is_held")),
el.attribute("frames_pending_string", ""),
el.attribute("frames_string")
));
x++;
el = root.elementsByTagName("post").at(x).toElement();
}
qDebug() << "KonaSearch: Search finished!";
searchIsDone = true;
emit searchFinished(this);
}
else {
qDebug() << "KonaSearch: ERROR: " << "Received HTTP error code: " << statusCode;
emit searchFailed(this, ERROR_SEARCH_HTTP);
}
}
void KonaSearch::responseHeaderReceived(QHttpResponseHeader resp) {
statusCode = resp.statusCode();
}

54
konasearch.h Executable file
View File

@ -0,0 +1,54 @@
#ifndef KONASEARCH_H
#define KONASEARCH_H
#include <QObject>
#include <QHttp>
#include <QFile>
#include <QUrl>
#include "konaclient.h"
#include "konaimage.h"
class KonaSearch : public QObject
{
Q_OBJECT
public:
KonaSearch(KonaClient *Kc, QString Tags = "", int Page=1, int Limit = 50);
~KonaSearch();
QString getTags() {return tags;}
int getPage() {return page;}
int getLimit() {return limit;}
void searchAgain();
QList<KonaImage*> getImages() {return result;}
bool isDone() {return searchIsDone;}
void newSearch(QString Tags = "", int Page=1, int Limit = 50);
int getTotalImages() {return totalImages;}
int getOffset() {return offset;}
private:
KonaClient *kc;
QString tags;
int page;
int limit;
QHttp *http;
QFile *file;
int statusCode;
int searchIsDone;
QList<KonaImage*> result;
int totalImages;
int offset;
signals:
void searchFinished(KonaSearch *ks);
void searchFailed(KonaSearch *ks, int errorCode);
public slots:
void requestFinished();
void responseHeaderReceived(QHttpResponseHeader resp);
};
#endif // KONASEARCH_H

10
konatag.cpp Executable file
View File

@ -0,0 +1,10 @@
#include "konatag.h"
KonaTag::KonaTag(int Id, QString Name, int Count, int Type, bool Ambiguous)
{
id = Id;
name = Name;
count = Count;
type = Type;
ambiguous = Ambiguous;
}

25
konatag.h Executable file
View File

@ -0,0 +1,25 @@
#ifndef KONATAG_H
#define KONATAG_H
#include <QObject>
class KonaTag : public QObject
{
Q_OBJECT
public:
KonaTag(int Id, QString Name, int Count, int Type, bool Ambiguous);
int getId() {return id;}
QString getName() {return name;}
int getCount() {return count;}
int getType() {return type;}
bool getAmbiguous() {return ambiguous;}
private:
int id;
QString name;
int count;
int type;
bool ambiguous;
};
#endif // KONATAG_H

131
konatags.cpp Executable file
View File

@ -0,0 +1,131 @@
#include "konatags.h"
#include <QDebug>
KonaTags::KonaTags(KonaClient *Kc, QString Name, int Limit, int Page, QString Order, int Id, int AfterId, QString NamePattern)
{
kc = Kc;
name = Name;
limit = Limit;
page = Page;
order = Order;
id = Id;
afterId = AfterId;
namePattern = NamePattern;
// Initialize temp file
int fileID = 0;
file = new QFile(kc->getTempDir() + SLASH + "tags_0");
while (file->exists()) {
fileID++;
file->setFileName(kc->getTempDir() + SLASH + "tags_" + QString::number(fileID));
}
// Prepare HTTP
http = new QHttp(kc->getServer());
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)),
this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
connect(http, SIGNAL(requestFinished(int,bool)),
this, SLOT(requestFinished()));
if (limit != -1) searchAgain();
else searchIsDone = true;
}
void KonaTags::searchAgain() {
searchIsDone = false;
statusCode = 0;
if (!file->open(QIODevice::ReadWrite)) {
qDebug() << "KonaTags: ERROR: Can't open temp file for search!";
emit searchFailed(this, ERROR_TAGS_TEMPFILE);
return;
}
QString optParams;
optParams += (id != -1 ? "&id=" + QString::number(id) : "");
optParams += (afterId != -1 ? "&after_id=" + QString::number(afterId) : "");
QUrl url("/tag/index.xml?name=" + name + "&page=" + QString::number(page) + "&limit=" + QString::number(limit) + "&order=" + order + "&name_pattern=" + namePattern + optParams);
http->get(url.toString(), file);
}
void KonaTags::requestFinished() {
if (statusCode == 200) {
file->flush();
file->reset();
QDomDocument doc ("search");
if (!doc.setContent(file)) {
qDebug() << "KonaSearch: ERROR: Can't parse xml!";
emit searchFailed(this, ERROR_SEARCH_XML);
file->close();
file->remove();
return;
}
file->close();
file->remove(); // We don't need it anymore
QDomElement root = doc.documentElement();
if (root.tagName() != "tags") {
qDebug() << "KonaTags: ERROR: Wrong root element!";
emit searchFailed(this, ERROR_TAGS_FORMAT);
return;
}
QDomElement el = root.firstChildElement("tag");
if (el.isNull()) {
qDebug() << "KonaTags: ERROR: Couldn't get first element!";
emit searchFailed(this, ERROR_TAGS_FORMAT);
return;
}
#define toBool(a) (a == "true" ? true : false)
int x = 0;
while (!el.isNull()) {
result.append(new KonaTag(el.attribute("id", "0").toInt(),
el.attribute("name"),
el.attribute("count").toInt(),
el.attribute("type").toInt(),
toBool(el.attribute("ambiguous"))));
x++;
el = root.elementsByTagName("tag").at(x).toElement();
}
qDebug() << "KonaTags: Search finished!";
searchIsDone = true;
emit searchFinished(this);
}
else {
qDebug() << "KonaTags: ERROR: " << "Received HTTP error code: " << statusCode;
emit searchFailed(this, ERROR_SEARCH_HTTP);
}
}
void KonaTags::responseHeaderReceived(QHttpResponseHeader resp) {
statusCode = resp.statusCode();
}
void KonaTags::newSearch(QString Name, int Limit, int Page, QString Order, int Id, int AfterId, QString NamePattern) {
// Reset
searchIsDone = false;
result.clear();
// Update search info to RAM
if (Name != "__KEEPOLD__") name = Name;
if (Limit != -1) limit = Limit;
if (Page != -1) page = Page;
if (Order != "__KEEPOLD__") order = Order;
if (Id != -1) id = Id;
if (AfterId != -1) afterId = AfterId;
if (NamePattern != "__KEEPOLD__") namePattern = NamePattern;
file->close();
file->remove();
searchAgain();
}

56
konatags.h Executable file
View File

@ -0,0 +1,56 @@
#ifndef KONATAGS_H
#define KONATAGS_H
#include <QObject>
#include <QHttp>
#include <QFile>
#include <QUrl>
#include <QtXml>
#include "konatag.h"
#include "konaclient.h"
#define ERROR_TAGS_TEMPFILE 1
#define ERROR_TAGS_FORMAT 2
#define ERROR_SEARCH_XML 3
#define ERROR_SEARCH_HTTP 4
class KonaTags : public QObject
{
Q_OBJECT
public:
// order can be date, count or name
KonaTags(KonaClient *Kc, QString Name, int Limit=20, int Page=1, QString Order="count", int Id = -1, int AfterId = -1, QString NamePattern="");
void searchAgain();
bool isDone() {return searchIsDone;}
QList<KonaTag*> getTags() {return result;}
void newSearch(QString Name = "__KEEPOLD__", int Limit = -1, int Page = -1, QString Order="__KEEPOLD__", int Id = -1, int AfterId = -1, QString NamePattern = "__KEEPOLD__");
private:
KonaClient *kc;
QString name;
int limit;
int page;
QString order;
int id;
int afterId;
QString namePattern;
QHttp *http;
QFile *file;
int statusCode;
int searchIsDone;
QList<KonaTag*> result;
signals:
void searchFinished(KonaTags *kt);
void searchFailed(KonaTags *kt, int errorCode);
public slots:
void requestFinished();
void responseHeaderReceived(QHttpResponseHeader resp);
};
#endif // KONATAGS_H

18
main.cpp Executable file
View File

@ -0,0 +1,18 @@
#include <QtGui/QApplication>
#include "mainwindow.h"
/*
TODO:
- Change "show image" source to jpeg.
- Add jpeg-download to KonaImage. -> CacheDir
*/
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

297
mainwindow.cpp Executable file
View File

@ -0,0 +1,297 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "konapreviewimageview.h"
#include <QScrollBar>
/*
NOTE #1: round results to get correct page maximum
TODO: Too much to list here.
*/
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
bottomPage = 1;
insertAtBeginning = false;
kc = new KonaClient(QDir::tempPath() + "/KonaClient", "/home/markus/Bilder/KonaChan/Cache", "/home/markus/Bilder/KonaChan/Archive");
flowLayout = new FlowLayout;
ui->listLayout->addLayout(flowLayout);
connect(ui->scrollList->verticalScrollBar(), SIGNAL(valueChanged(int)),
this, SLOT(onScroll(int)));
search = new KonaSearch(kc, ui->txtSearch->text().toStdString().data(), 1);
if (search->isDone()) searchFinished(search);
else connect(search, SIGNAL(searchFinished(KonaSearch*)),
this, SLOT(searchFinished(KonaSearch*)));
tags = new KonaTags(kc, "", RELATED_TAGS_AMOUNT);
if (tags->isDone()) tagsFinished(tags);
else connect(tags, SIGNAL(searchFinished(KonaTags*)),
this, SLOT(tagsFinished(KonaTags*)));
relatedTags = new KonaRelatedTags(kc, "", "");
connect(relatedTags, SIGNAL(searchFinished(KonaRelatedTags*)),
this, SLOT(relatedTagsFinished(KonaRelatedTags*)));
imageViewer = new ImageViewer(this);
connect(imageViewer, SIGNAL(loadNext()),
this, SLOT(jumpNext()));
connect(imageViewer, SIGNAL(loadPrev()),
this, SLOT(jumpPrev()));
}
MainWindow::~MainWindow()
{
//search->deleteLater();
//kc->deleteLater();
delete ui;
}
void MainWindow::jumpPrev() {
QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();
int x;
for (x=0; x < kpiv.count(); x++) {
if (x == 0) {
qDebug() << "MainWindow: RELOAD <";
ui->scrollList->verticalScrollBar()->setValue(1);
ui->scrollList->verticalScrollBar()->setValue(0);
}
if (x < 1) { // Make sure we don't try to load non existent images
qDebug() << "WARN! MainWindow: NOT LOADED YET OR END OF LIST";
}
else if (kpiv.at(x)->getKonaImage()->getId() == imageViewer->getCurrentId()) {
qDebug() << "JUMP";
showImage(kpiv.at(x-1)->getKonaImage());
break;
}
}
if (x == kpiv.count()) showImage(kpiv.at(0)->getKonaImage());
}
void MainWindow::jumpNext() {
QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();
int x;
for (x=0; x < kpiv.count(); x++) { // Loop through curerntly available images
if (x + 1 + PRELOAD_AMOUNT == kpiv.count()) {
qDebug() << "MainWindow: RELOAD >";
ui->scrollList->verticalScrollBar()->setValue(ui->scrollList->verticalScrollBar()->maximum());
}
if (x + 1 >= kpiv.count()) { // Make sure we don't try to load non existent images
qDebug() << "WARN! MainWindow: NOT LOADED YET OR END OF LIST";
}
else if (kpiv.at(x)->getKonaImage()->getId() == imageViewer->getCurrentId()) {
showImage(kpiv.at(x+1)->getKonaImage());
break;
}
}
if (x == kpiv.count()) showImage(kpiv.at(0)->getKonaImage());
}
void MainWindow::onScroll(int value) {
if (!search->isDone()) return; // Wait for current search to finish
if (ui->scrollList->verticalScrollBar()->maximum() <= 0) return;
if ((value/ui->scrollList->verticalScrollBar()->maximum())) {
// hit lower end
if (bottomPage <= ui->pageJumpNum->maximum()) { // TODO: might be wrong
//ui->scrollList->verticalScrollBar()->setValue(1); //allow user to continue scrolling up
insertAtBeginning = false;
search->newSearch(currentSearch.toStdString().data(), ++bottomPage);
}
}
else if (((float) value/ (float)ui->scrollList->verticalScrollBar()->maximum()) == 0){
// hit upper end
if (upperPage > 1) {// TODO: Sort the other way round on receive
insertAtBeginning=true;
search->newSearch(currentSearch.toStdString().data(), --upperPage);
}
}
}
void MainWindow::jumpToPage() {
insertAtBeginning = false;
ui->scrollList->verticalScrollBar()->setValue(1);
upperPage = ui->pageJumpNum->value();
bottomPage = ui->pageJumpNum->value();
clearList();
search->newSearch(currentSearch.toStdString().data(), ui->pageJumpNum->value());
}
void MainWindow::searchPools() {
qDebug() << "POOLS not implemented yet!";
}
void MainWindow::searchPosts() {
insertAtBeginning=false;
ui->scrollList->verticalScrollBar()->setValue(0);
ui->btnJump->setEnabled(false);
upperPage = 1;
bottomPage = 1;
clearList();
currentSearch = ui->txtSearch->text();
search->newSearch(currentSearch.toStdString().data(), 1);
if (ui->txtSearch->text() == "") {
tags->newSearch(currentSearch);
}
else {
relatedTags->newSearch(currentSearch);
}
}
void MainWindow::searchFinished(KonaSearch *ks) {
ui->btnJump->setEnabled(true);
ui->pageJumpNum->setMaximum(ks->getTotalImages() / ITEMS_PER_SEARCH); // TODO: ROUND to get correct values (NOTE #1)
ui->statusBar->showMessage("Search returned " + QString::number(ks->getTotalImages()) + " results.");
for (int x=0; x < ks->getImages().count(); x++) {
// Get the KonaImage
KonaImage *ki = ks->getImages().at(x);
// Check whether it already exists (shouldn't be possible but who knows...)
QList<KonaPreviewImageView*> elEx = findChildren<KonaPreviewImageView*>(QString::number(ki->getId()));
if (elEx.count() > 0) {
qDebug() << "Main: searchFinished: Item already existed: " << ki->getId();
}
else {
// Add new frame to list
KonaPreviewImageView *temp = new KonaPreviewImageView();
temp->setObjectName(QString::number(ki->getId()));
if (insertAtBeginning) {
flowLayout->insertWidgetAt(temp, 0); // Add @ beginning
}
else {
flowLayout->addWidget(temp); // Add @ end
}
// Grab the new handle
KonaPreviewImageView* kpiv = findChild<KonaPreviewImageView*>(QString::number(ki->getId()));
// Update image
connect(ki, SIGNAL(previewDownloaded(KonaImage*,QString)),
kpiv, SLOT(previewDownloaded(KonaImage*,QString)));
connect(kpiv, SIGNAL(buttonClicked(KonaImage*)),
this, SLOT(downloadImage(KonaImage*)));
connect(kpiv, SIGNAL(imageClicked(KonaImage*)),
this, SLOT(showImage(KonaImage*)));
kpiv->setCaption("Download @ " + QString::number(ki->getWidth()) + " x " + QString::number(ki->getHeight())); //temp
ki->DownloadPreview(); //Download!
}
}
}
void MainWindow::showImage(KonaImage *Ki) {
qDebug() << "MainWindow: SHOW " << Ki->getId();
imageViewer->showLoading();
connect(Ki, SIGNAL(imageDownloaded(KonaImage*,QString)),
imageViewer, SLOT(setImage(KonaImage*)));
Ki->DownloadImage();
if (!imageViewer->isVisible()) {
imageViewer->show();
}
// PRELOADING (not clean but functional)
QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();
int x;
for (x=0; x < kpiv.count(); x++) {
if (x < 1) { // Make sure we don't try to load non existent images
}
else if (kpiv.at(x)->getKonaImage()->getId() == Ki->getId()) {
// Preloading
int y;
for (y=0; y < PRELOAD_AMOUNT; y++) { // TODO: Add preload limit to appconfig
if (x+1+y < kpiv.count()) {
qDebug() << "MainWindow: Will preload image " << kpiv.at(x+1+y)->getKonaImage()->getId();
//downloadImage(kpiv.at(x+1+y)->getKonaImage(), false);
connect(kpiv.at(x+y)->getKonaImage(), SIGNAL(imageDownloaded(KonaImage*,QString)),
kpiv.at(x+1+y)->getKonaImage(), SLOT(DownloadImage()));
}
}
break;
}
}
}
void MainWindow::downloadImage(KonaImage *Ki) {
qDebug() << "MainWindow: downloadImage " + Ki->getId();
qDebug() << "MainWindow: downloadImage: THIS FUNCTION IS DEPRECTAED AND WILL BE REMOVED!";
downloadImage(Ki, true);
}
void MainWindow::downloadImage(KonaImage *Ki, bool overwrite) {
qDebug() << "DOWNLOAD " << Ki->getId();
ui->statusBar->showMessage("Downloading image " + QString::number(Ki->getId()) + "...");
Ki->DownloadImage(overwrite); // TODO: Do we want to have true here?
}
void MainWindow::tagClicked(QString link) {
QStringList temp = link.split("?");
if (temp.at(0) == "srcTag") {
ui->txtSearch->setText(temp.at(1));
searchPosts(); // TODO: later it needs to support pools!
}
else if (temp.at(0) == "addTag") {
if (ui->txtSearch->text().toLower().indexOf(temp.at(1).toLower()) == -1) {
ui->txtSearch->setText(ui->txtSearch->text() + " " + temp.at(1));
searchPosts(); // TODO: support pools
}
}
}
void MainWindow::tagsFinished(KonaTags *kt)
{
QString out;
for (int x=0; x < kt->getTags().count(); x++) {
KonaTag *tag = kt->getTags().at(x);
out.append("<a href='addTag?" + tag->getName() + "'>+</a><a href='srcTag?" + tag->getName() + "'>" + tag->getName() + "</a> <font size=2>(" + QString::number(tag->getCount()) + ")</font><br />");
}
ui->lblTags->setText(out);
}
void MainWindow::relatedTagsFinished(KonaRelatedTags *krt) //TODO: Merge with tagsFinished()
{
QString out;
for (int x=0; x < krt->getTags().count(); x++) {
KonaTag *tag = krt->getTags().at(x);
out.append("<a href='addTag?" + tag->getName() + "'>+</a><a href='srcTag?" + tag->getName() + "'>" + tag->getName() + "</a> <font size=2>(" + QString::number(tag->getCount()) + ")</font><br />");
}
ui->lblTags->setText(out);
}
void MainWindow::clearList() {
QLayoutItem* item;
while ( ( item = flowLayout->takeAt( 0 ) ) != NULL )
{
delete item->widget();
delete item;
}
}

80
mainwindow.h Executable file
View File

@ -0,0 +1,80 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "konaclient.h"
#include "konasearch.h"
#include "konaimage.h"
#include "konatags.h"
#include "konatag.h"
#include "konarelatedtags.h"
#include <QStyle>
#include "flowlayout.h"
#include "imageviewer.h"
#define ITEMS_PER_SEARCH 50
#define RELATED_TAGS_AMOUNT 10
#define SEARCHTYPE_POSTS 0
#define SEARCHTYPE_POOLS 1
// SETTINGS
#define PRELOAD_AMOUNT 3 // TODO:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
// GUI Events
void onScroll(int value);
void searchPosts();
void searchPools();
void jumpToPage();
void tagClicked(QString link);
// Int
void searchFinished(KonaSearch *ks);
void tagsFinished(KonaTags *kt);
void relatedTagsFinished(KonaRelatedTags *krt);
void downloadImage(KonaImage *Ki);
void downloadImage(KonaImage *Ki, bool overwrite);
void showImage(KonaImage *Ki);
void jumpNext();
void jumpPrev();
private:
Ui::MainWindow *ui;
KonaClient *kc;
KonaSearch *search;
KonaTags *tags;
KonaRelatedTags *relatedTags;
FlowLayout *flowLayout;
ImageViewer *imageViewer;
bool insertAtBeginning;
void clearList();
int upperPage;
int bottomPage;
QString currentSearch;
};
#endif // MAINWINDOW_H

503
mainwindow.ui Executable file
View File

@ -0,0 +1,503 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>480</height>
</size>
</property>
<property name="windowTitle">
<string>KonaClient</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QScrollArea" name="scrollList">
<property name="styleSheet">
<string notr="true">/* background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(122, 122, 122, 255));*/</string>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>663</width>
<height>533</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="listLayout">
<property name="spacing">
<number>6</number>
</property>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>&amp;View</string>
</property>
<widget class="QMenu" name="menuWidgets">
<property name="title">
<string>&amp;Widgets</string>
</property>
<addaction name="actionSearch"/>
<addaction name="actionNavigation"/>
<addaction name="actionTags"/>
</widget>
<addaction name="menuWidgets"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>&amp;Help</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QDockWidget" name="searchWidget">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLineEdit" name="txtSearch">
<property name="toolTip">
<string>Remember to replace spaces per underscores. For example &quot;Suzumiya Haruhi&quot; -&gt; suzumiya_haruhi
You can use * as a wildcard. For example &quot;higurashi*&quot;</string>
</property>
<property name="statusTip">
<string>Enter tags seperated by a space.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="searchButtonLayout">
<item>
<widget class="QPushButton" name="btnSearchPosts">
<property name="statusTip">
<string>Search in posts</string>
</property>
<property name="text">
<string>&amp;Posts</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnSearchPools">
<property name="statusTip">
<string>Search in pools</string>
</property>
<property name="text">
<string>P&amp;ools</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="navigationWidget">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="windowTitle">
<string>Navigation</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Jump to page:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="pageJumpNum">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnJump">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Go!</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="tagsWidget">
<property name="windowTitle">
<string>Tags</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_4">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>194</width>
<height>304</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblTags">
<property name="text">
<string>[Tags]</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1000</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="actionQuit">
<property name="text">
<string>&amp;Quit</string>
</property>
</action>
<action name="actionSearch">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Search</string>
</property>
<property name="shortcut">
<string>Alt+S</string>
</property>
</action>
<action name="actionNavigation">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Navigation</string>
</property>
<property name="shortcut">
<string>Alt+N</string>
</property>
</action>
<action name="actionTags">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Tags</string>
</property>
<property name="shortcut">
<string>Alt+T</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections>
<connection>
<sender>btnSearchPosts</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>searchPosts()</slot>
<hints>
<hint type="sourcelabel">
<x>58</x>
<y>117</y>
</hint>
<hint type="destinationlabel">
<x>69</x>
<y>148</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnSearchPools</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>searchPools()</slot>
<hints>
<hint type="sourcelabel">
<x>172</x>
<y>119</y>
</hint>
<hint type="destinationlabel">
<x>200</x>
<y>146</y>
</hint>
</hints>
</connection>
<connection>
<sender>txtSearch</sender>
<signal>returnPressed()</signal>
<receiver>MainWindow</receiver>
<slot>searchPosts()</slot>
<hints>
<hint type="sourcelabel">
<x>146</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>26</x>
<y>145</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnJump</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>jumpToPage()</slot>
<hints>
<hint type="sourcelabel">
<x>186</x>
<y>232</y>
</hint>
<hint type="destinationlabel">
<x>285</x>
<y>348</y>
</hint>
</hints>
</connection>
<connection>
<sender>lblTags</sender>
<signal>linkActivated(QString)</signal>
<receiver>MainWindow</receiver>
<slot>tagClicked(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>61</x>
<y>298</y>
</hint>
<hint type="destinationlabel">
<x>200</x>
<y>558</y>
</hint>
</hints>
</connection>
<connection>
<sender>tagsWidget</sender>
<signal>visibilityChanged(bool)</signal>
<receiver>actionTags</receiver>
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>127</x>
<y>265</y>
</hint>
<hint type="destinationlabel">
<x>282</x>
<y>261</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionTags</sender>
<signal>toggled(bool)</signal>
<receiver>tagsWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>97</x>
<y>412</y>
</hint>
</hints>
</connection>
<connection>
<sender>searchWidget</sender>
<signal>visibilityChanged(bool)</signal>
<receiver>actionSearch</receiver>
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>97</x>
<y>82</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionSearch</sender>
<signal>toggled(bool)</signal>
<receiver>searchWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>97</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>navigationWidget</sender>
<signal>visibilityChanged(bool)</signal>
<receiver>actionNavigation</receiver>
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>97</x>
<y>193</y>
</hint>
<hint type="destinationlabel">
<x>97</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionNavigation</sender>
<signal>toggled(bool)</signal>
<receiver>navigationWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>97</x>
<y>193</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionQuit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>439</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>searchPosts()</slot>
<slot>searchPools()</slot>
<slot>jumpToPage()</slot>
<slot>tagClicked(QString)</slot>
</slots>
</ui>