From cf5d399f002715ec8d31a00a729a396b2292420e Mon Sep 17 00:00:00 2001 From: nowrep Date: Tue, 22 May 2012 11:46:22 +0200 Subject: [PATCH] Added possibility to change icon of bookmarks - created new IconChooser class with option to choose icon from file or icon from database Closes #401 --- src/lib/bookmarks/bookmarksmanager.cpp | 29 ++++- src/lib/bookmarks/bookmarksmanager.h | 1 + src/lib/bookmarks/bookmarksmodel.cpp | 42 +++++++- src/lib/bookmarks/bookmarksmodel.h | 3 +- src/lib/lib.pro | 9 +- src/lib/opensearch/editsearchengine.cpp | 11 +- src/lib/opensearch/editsearchengine.ui | 2 +- src/lib/other/iconchooser.cpp | 130 ++++++++++++++++++++++ src/lib/other/iconchooser.h | 60 +++++++++++ src/lib/other/iconchooser.ui | 138 ++++++++++++++++++++++++ src/lib/webview/tabwidget.cpp | 1 - 11 files changed, 407 insertions(+), 19 deletions(-) create mode 100644 src/lib/other/iconchooser.cpp create mode 100644 src/lib/other/iconchooser.h create mode 100644 src/lib/other/iconchooser.ui diff --git a/src/lib/bookmarks/bookmarksmanager.cpp b/src/lib/bookmarks/bookmarksmanager.cpp index 0b41c57d1..e5903b035 100644 --- a/src/lib/bookmarks/bookmarksmanager.cpp +++ b/src/lib/bookmarks/bookmarksmanager.cpp @@ -27,6 +27,7 @@ #include "browsinglibrary.h" #include "globalfunctions.h" #include "bookmarksimportdialog.h" +#include "iconchooser.h" #include "webtab.h" #include @@ -66,8 +67,6 @@ BookmarksManager::BookmarksManager(QupZilla* mainClass, QWidget* parent) connect(deleteAction, SIGNAL(activated()), this, SLOT(deleteItem())); ui->bookmarksTree->setDefaultItemShowMode(TreeWidget::ItemsExpanded); - - //QTimer::singleShot(0, this, SLOT(refreshTable())); } void BookmarksManager::importBookmarks() @@ -151,6 +150,24 @@ void BookmarksManager::renameBookmark() ui->bookmarksTree->editItem(item, 0); } +void BookmarksManager::changeIcon() +{ + QTreeWidgetItem* item = ui->bookmarksTree->currentItem(); + if (!item) { + return; + } + + int id = item->data(0, Qt::UserRole + 10).toInt(); + QIcon icon; + + IconChooser chooser(this); + icon = chooser.exec(); + + if (!icon.isNull()) { + m_bookmarksModel->changeIcon(id, icon); + } +} + void BookmarksManager::itemChanged(QTreeWidgetItem* item) { if (!item || m_isRefreshing || item->text(1).isEmpty()) { @@ -213,6 +230,7 @@ void BookmarksManager::moveBookmark() if (!item) { return; } + if (QAction* action = qobject_cast(sender())) { int id = item->data(0, Qt::UserRole + 10).toInt(); @@ -225,7 +243,8 @@ void BookmarksManager::contextMenuRequested(const QPoint &position) if (!ui->bookmarksTree->itemAt(position)) { return; } - QString link = ui->bookmarksTree->itemAt(position)->text(1); + + QUrl link = ui->bookmarksTree->itemAt(position)->data(0, Qt::UserRole + 11).toUrl(); if (link.isEmpty()) { QString folderName = ui->bookmarksTree->itemAt(position)->text(0); QMenu menu; @@ -268,6 +287,7 @@ void BookmarksManager::contextMenuRequested(const QPoint &position) menu.addMenu(&moveMenu); menu.addSeparator(); + menu.addAction(tr("Change icon"), this, SLOT(changeIcon())); menu.addAction(tr("Rename bookmark"), this, SLOT(renameBookmark())); menu.addAction(tr("Remove bookmark"), this, SLOT(deleteItem())); @@ -331,6 +351,7 @@ void BookmarksManager::refreshTable() item->setToolTip(1, url.toEncoded()); item->setData(0, Qt::UserRole + 10, id); + item->setData(0, Qt::UserRole + 11, url); item->setIcon(0, icon); item->setFlags(item->flags() | Qt::ItemIsEditable); ui->bookmarksTree->addTopLevelItem(item); @@ -359,6 +380,7 @@ void BookmarksManager::refreshTable() item->setToolTip(1, url.toEncoded()); item->setData(0, Qt::UserRole + 10, id); + item->setData(0, Qt::UserRole + 11, url); item->setIcon(0, icon); item->setFlags(item->flags() | Qt::ItemIsEditable); } @@ -378,6 +400,7 @@ void BookmarksManager::addBookmark(const BookmarksModel::Bookmark &bookmark) item->setText(0, bookmark.title); item->setText(1, bookmark.url.toEncoded()); item->setData(0, Qt::UserRole + 10, bookmark.id); + item->setData(0, Qt::UserRole + 11, bookmark.url); item->setIcon(0, qIconProvider->iconFromImage(bookmark.image)); item->setToolTip(0, bookmark.title); item->setToolTip(1, bookmark.url.toEncoded()); diff --git a/src/lib/bookmarks/bookmarksmanager.h b/src/lib/bookmarks/bookmarksmanager.h index dbdd7a3d5..1f52217c2 100644 --- a/src/lib/bookmarks/bookmarksmanager.h +++ b/src/lib/bookmarks/bookmarksmanager.h @@ -63,6 +63,7 @@ private slots: void itemControlClicked(QTreeWidgetItem* item); void moveBookmark(); void renameBookmark(); + void changeIcon(); void importBookmarks(); void addFolder(const QString &name); diff --git a/src/lib/bookmarks/bookmarksmodel.cpp b/src/lib/bookmarks/bookmarksmodel.cpp index f263641e6..e29776529 100644 --- a/src/lib/bookmarks/bookmarksmodel.cpp +++ b/src/lib/bookmarks/bookmarksmodel.cpp @@ -280,13 +280,13 @@ bool BookmarksModel::editBookmark(int id, const QString &title, const QUrl &url, if (title.isEmpty() && url.isEmpty() && folder.isEmpty()) { return false; } + QSqlQuery query; - if (!query.exec("SELECT title, url, folder, icon FROM bookmarks WHERE id = " + QString::number(id))) { + query.exec("SELECT title, url, folder, icon FROM bookmarks WHERE id = " + QString::number(id)); + if (!query.next()) { return false; } - query.next(); - Bookmark before; before.id = id; before.title = query.value(0).toString(); @@ -318,6 +318,42 @@ bool BookmarksModel::editBookmark(int id, const QString &title, const QUrl &url, return true; } +bool BookmarksModel::changeIcon(int id, const QIcon &icon) +{ + QSqlQuery query; + query.exec("SELECT title, url, folder, icon FROM bookmarks WHERE id = " + QString::number(id)); + if (!query.next()) { + return false; + } + + Bookmark before; + before.id = id; + before.title = query.value(0).toString(); + before.url = query.value(1).toUrl(); + before.folder = query.value(2).toString(); + before.image = QImage::fromData(query.value(3).toByteArray()); + before.inSubfolder = isSubfolder(before.folder); + + Bookmark after = before; + after.image = icon.pixmap(16).toImage(); + + query.prepare("UPDATE bookmarks SET icon = ? WHERE id = ?"); + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + after.image.save(&buffer, "PNG"); + query.bindValue(0, buffer.data()); + query.bindValue(1, id); + + if (!query.exec()) { + return false; + } + + emit bookmarkEdited(before, after); + mApp->sendMessages(Qz::AM_BookmarksChanged, true); + return true; +} + bool BookmarksModel::createFolder(const QString &name) { if (isFolder(name)) { diff --git a/src/lib/bookmarks/bookmarksmodel.h b/src/lib/bookmarks/bookmarksmodel.h index aeb51e279..13098853c 100644 --- a/src/lib/bookmarks/bookmarksmodel.h +++ b/src/lib/bookmarks/bookmarksmodel.h @@ -86,8 +86,7 @@ public: void removeBookmark(const QList list); bool editBookmark(int id, const QString &title = "", const QUrl &url = QUrl(), const QString &folder = ""); -// bool editBookmark(int id, const QString &title, const QString &folder); -// bool editBookmark(int id, const QUrl &url, const QString &title); + bool changeIcon(int id, const QIcon &icon); bool createFolder(const QString &name); void removeFolder(const QString &name); diff --git a/src/lib/lib.pro b/src/lib/lib.pro index ed7f415a5..fc8e225eb 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -177,7 +177,8 @@ SOURCES += \ history/historymodel.cpp \ history/historyview.cpp \ history/historyitem.cpp \ - tools/headerview.cpp + tools/headerview.cpp \ + other/iconchooser.cpp HEADERS += \ webview/tabpreview.h \ @@ -326,7 +327,8 @@ HEADERS += \ history/historymodel.h \ history/historyview.h \ history/historyitem.h \ - tools/headerview.h + tools/headerview.h \ + other/iconchooser.h FORMS += \ preferences/autofillmanager.ui \ @@ -367,7 +369,8 @@ FORMS += \ opensearch/searchenginesdialog.ui \ opensearch/editsearchengine.ui \ bookmarksimport/bookmarksimportdialog.ui \ - other/checkboxdialog.ui + other/checkboxdialog.ui \ + other/iconchooser.ui RESOURCES += \ data/icons.qrc \ diff --git a/src/lib/opensearch/editsearchengine.cpp b/src/lib/opensearch/editsearchengine.cpp index 2520f26f9..7ee292097 100644 --- a/src/lib/opensearch/editsearchengine.cpp +++ b/src/lib/opensearch/editsearchengine.cpp @@ -17,6 +17,7 @@ * ============================================================ */ #include "editsearchengine.h" #include "ui_editsearchengine.h" +#include "iconchooser.h" #include @@ -87,12 +88,10 @@ void EditSearchEngine::hideIconLabels() void EditSearchEngine::chooseIcon() { - const QString &fileTypes = QString("%3(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff)").arg(tr("Image files")); + IconChooser chooser(this); + QIcon icon = chooser.exec(); - QString path = QFileDialog::getOpenFileName(this, tr("Choose icon..."), QDir::homePath(), fileTypes); - if (path.isEmpty()) { - return; + if (!icon.isNull()) { + setIcon(icon); } - - setIcon(QIcon(path)); } diff --git a/src/lib/opensearch/editsearchengine.ui b/src/lib/opensearch/editsearchengine.ui index c28b54598..577d309d9 100644 --- a/src/lib/opensearch/editsearchengine.ui +++ b/src/lib/opensearch/editsearchengine.ui @@ -94,7 +94,7 @@ - Add from file ... + Change... diff --git a/src/lib/other/iconchooser.cpp b/src/lib/other/iconchooser.cpp new file mode 100644 index 000000000..ca9ae590d --- /dev/null +++ b/src/lib/other/iconchooser.cpp @@ -0,0 +1,130 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#include "iconchooser.h" +#include "ui_iconchooser.h" + +#include +#include + +IconChooser::IconChooser(QWidget* parent) + : QDialog(parent), + ui(new Ui::IconChooser) +{ + ui->setupUi(this); + + ui->iconList->setItemDelegate(new IconChooserDelegate(ui->iconList)); + + connect(ui->chooseFile, SIGNAL(clicked()), this, SLOT(chooseFile())); + connect(ui->siteUrl, SIGNAL(textChanged(QString)), this, SLOT(searchIcon(QString))); +} + +void IconChooser::chooseFile() +{ + const QString &fileTypes = QString("%3(*.png *.jpg *.jpeg *.gif)").arg(tr("Image files")); + const QString &path = QFileDialog::getOpenFileName(this, tr("Choose icon..."), QDir::homePath(), fileTypes); + + if (path.isEmpty()) { + return; + } + + ui->iconList->clear(); + QIcon icon(path); + + if (!icon.isNull()) { + QListWidgetItem* item = new QListWidgetItem(ui->iconList); + item->setIcon(icon); + + ui->iconList->setCurrentItem(item); + } +} + +void IconChooser::searchIcon(const QString &string) +{ + if (string.size() < 4) { + return; + } + + ui->iconList->clear(); + + QSqlQuery query; + query.prepare("SELECT icon FROM icons WHERE url LIKE ? LIMIT 20"); + query.bindValue(0, QString("%%1%").arg(string)); + query.exec(); + + while (query.next()) { + QImage image = QImage::fromData(query.value(0).toByteArray()); + if (!image.isNull()) { + QListWidgetItem* item = new QListWidgetItem(ui->iconList); + item->setIcon(QPixmap::fromImage(image)); + } + } +} + +QIcon IconChooser::exec() +{ + QIcon icon; + int status = QDialog::exec(); + + if (status == QDialog::Accepted) { + QList selectedItems = ui->iconList->selectedItems(); + if (!selectedItems.isEmpty()) { + icon = selectedItems.at(0)->icon(); + } + } + + // Ensure we are returning 16×16px icon + if (!icon.isNull()) { + icon = icon.pixmap(16); + } + + return icon; +} + +IconChooser::~IconChooser() +{ + delete ui; +} + +IconChooserDelegate::IconChooserDelegate(QWidget* parent) + : QStyledItemDelegate(parent) +{ +} + +void IconChooserDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + + const QWidget* w = opt.widget; + const QStyle* style = w ? w->style() : QApplication::style(); + + // Draw background + style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, w); + + // Draw icon + QIcon icon = index.data(Qt::DecorationRole).value(); + icon.paint(painter, opt.rect); +} + +QSize IconChooserDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + return QSize(48, 48); +} diff --git a/src/lib/other/iconchooser.h b/src/lib/other/iconchooser.h new file mode 100644 index 000000000..ad7bb7502 --- /dev/null +++ b/src/lib/other/iconchooser.h @@ -0,0 +1,60 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef ICONCHOOSER_H +#define ICONCHOOSER_H + +#include +#include + +#include "qz_namespace.h" + +class QIcon; + +namespace Ui +{ +class IconChooser; +} + +class QT_QUPZILLA_EXPORT IconChooser : public QDialog +{ + Q_OBJECT + +public: + explicit IconChooser(QWidget* parent = 0); + ~IconChooser(); + + QIcon exec(); + +private slots: + void chooseFile(); + void searchIcon(const QString &string); + +private: + Ui::IconChooser* ui; +}; + +class QT_QUPZILLA_EXPORT IconChooserDelegate : public QStyledItemDelegate +{ +public: + explicit IconChooserDelegate(QWidget* parent = 0); + + void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +#endif // ICONCHOOSER_H diff --git a/src/lib/other/iconchooser.ui b/src/lib/other/iconchooser.ui new file mode 100644 index 000000000..a16be04de --- /dev/null +++ b/src/lib/other/iconchooser.ui @@ -0,0 +1,138 @@ + + + IconChooser + + + + 0 + 0 + 388 + 326 + + + + Choose icon... + + + + + + From file + + + + 0 + + + + + Image (.png, .jpg, .jpeg, .gif) + + + + + + + + 0 + 0 + + + + Choose file... + + + + + + + + + + From database + + + + 0 + + + + + Site Url: + + + + + + + + + + + + + Qt::Horizontal + + + + + + + QListView::Static + + + QListView::Adjust + + + QListView::IconMode + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + IconChooser + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + IconChooser + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/lib/webview/tabwidget.cpp b/src/lib/webview/tabwidget.cpp index ee1e949f2..89d0ebe35 100644 --- a/src/lib/webview/tabwidget.cpp +++ b/src/lib/webview/tabwidget.cpp @@ -315,7 +315,6 @@ void TabWidget::closeTab(int index) index = currentIndex(); } - WebTab* webTab = weTab(index); if (!webTab) { return;