1 /* This file is (c) 2017 Abs62 2 * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ 3 4 #ifndef __FAVORITIESPANEWIDGET_HH__INCLUDED__ 5 #define __FAVORITIESPANEWIDGET_HH__INCLUDED__ 6 7 #include <QWidget> 8 #include <QSize> 9 #include <QAbstractItemModel> 10 #include <QLabel> 11 #include <QHBoxLayout> 12 #include <QMenu> 13 #include <QDomNode> 14 #include <QList> 15 #include <QMimeData> 16 17 #include <config.hh> 18 #include "delegate.hh" 19 #include "treeview.hh" 20 21 class FavoritesModel; 22 23 class FavoritesPaneWidget : public QWidget 24 { 25 Q_OBJECT 26 public: FavoritesPaneWidget(QWidget * parent=0)27 FavoritesPaneWidget( QWidget * parent = 0 ): QWidget( parent ), 28 itemSelectionChanged( false ) 29 , listItemDelegate( 0 ) 30 , m_favoritesModel( 0 ) 31 , timerId( 0 ) 32 {} 33 34 virtual ~FavoritesPaneWidget(); 35 sizeHint() const36 virtual QSize sizeHint() const 37 { return QSize( 204, 204 ); } 38 39 void setUp( Config::Class * cfg, QMenu * menu ); 40 41 void addHeadword( QString const & path, QString const & headword ); 42 43 bool removeHeadword( QString const & path, QString const & headword ); 44 45 // Export/import Favorites 46 void getDataInXml( QByteArray & dataStr ); 47 void getDataInPlainText( QString & dataStr ); 48 bool setDataFromXml( QString const & dataStr ); 49 setFocusOnTree()50 void setFocusOnTree() 51 { m_favoritesTree->setFocus(); } 52 53 // Set interval for periodical save 54 void setSaveInterval( unsigned interval ); 55 56 // Return true if headwors is already presented in Favorites 57 bool isHeadwordPresent( QString const & path, QString const & headword ); 58 59 void saveData(); 60 61 signals: 62 void favoritesItemRequested( QString const & word, QString const & faforitesFolder ); 63 64 protected: 65 virtual void timerEvent( QTimerEvent * ev ); 66 67 private slots: 68 void emitFavoritesItemRequested(QModelIndex const &); 69 void onSelectionChanged(QItemSelection const & selection); 70 void onItemClicked(QModelIndex const & idx); 71 void showCustomMenu(QPoint const & pos); 72 void deleteSelectedItems(); 73 void copySelectedItems(); 74 void addFolder(); 75 76 private: 77 virtual bool eventFilter( QObject *, QEvent * ); 78 79 Config::Class * m_cfg ; 80 TreeView * m_favoritesTree; 81 QMenu * m_favoritesMenu; 82 QAction * m_deleteSelectedAction; 83 QAction * m_separator; 84 QAction * m_copySelectedToClipboard; 85 QAction * m_addFolder; 86 87 QWidget favoritesPaneTitleBar; 88 QHBoxLayout favoritesPaneTitleBarLayout; 89 QLabel favoritesLabel; 90 91 /// needed to avoid multiple notifications 92 /// when selecting items via mouse and keyboard 93 bool itemSelectionChanged; 94 95 WordListItemDelegate * listItemDelegate; 96 FavoritesModel * m_favoritesModel; 97 98 int timerId; 99 }; 100 101 102 class TreeItem 103 { 104 public: 105 enum Type { Word, Folder, Root }; 106 107 TreeItem( const QVariant &data, TreeItem *parent = 0, Type type_ = Word ); 108 ~TreeItem(); 109 110 void appendChild( TreeItem * child ); 111 112 void insertChild( int row, TreeItem * item ); 113 114 // Remove child from list and delete it 115 void deleteChild( int row ); 116 117 TreeItem * child( int row ) const; 118 int childCount() const; 119 QVariant data() const; 120 void setData( const QVariant & newData ); 121 int row() const; 122 TreeItem * parent(); 123 type() const124 Type type() const 125 { return m_type; } 126 127 Qt::ItemFlags flags() const; 128 setExpanded(bool expanded)129 void setExpanded( bool expanded ) 130 { m_expanded = expanded; } 131 isExpanded() const132 bool isExpanded() const 133 { return m_expanded; } 134 135 // Full path from root folder 136 QString fullPath() const; 137 138 // Duplicate item with all childs 139 TreeItem * duplicateItem( TreeItem * newParent ) const; 140 141 // Check if item is ancestor of this element 142 bool haveAncestor( TreeItem * item ); 143 144 // Check if same item already presented between childs 145 bool haveSameItem( TreeItem * item, bool allowSelf ); 146 147 // Retrieve text from all childs 148 QStringList getTextFromAllChilds() const; 149 150 private: 151 QList< TreeItem * > childItems; 152 QVariant itemData; 153 TreeItem *parentItem; 154 Type m_type; 155 bool m_expanded; 156 }; 157 158 class FavoritesModel : public QAbstractItemModel 159 { 160 Q_OBJECT 161 public: 162 explicit FavoritesModel( QString favoritesFilename, QObject * parent = 0 ); 163 ~FavoritesModel(); 164 165 QVariant data( const QModelIndex &index, int role ) const; 166 Qt::ItemFlags flags( const QModelIndex &index ) const; 167 QVariant headerData( int section, Qt::Orientation orientation, 168 int role = Qt::DisplayRole ) const; 169 QModelIndex index( int row, int column, 170 const QModelIndex &parent = QModelIndex() ) const; 171 QModelIndex parent( const QModelIndex &index ) const; 172 int rowCount( const QModelIndex &parent = QModelIndex() ) const; 173 int columnCount( const QModelIndex &parent = QModelIndex() ) const; 174 bool removeRows( int row, int count, const QModelIndex &parent ); 175 bool setData( const QModelIndex &index, const QVariant &value, int role ); 176 177 // Drag & drop support 178 Qt::DropActions supportedDropActions() const; 179 QStringList mimeTypes() const; 180 QMimeData *mimeData(const QModelIndexList &indexes) const; 181 bool dropMimeData(const QMimeData *data, Qt::DropAction action, 182 int row, int column, const QModelIndex &par); 183 184 // Restore nodes expanded state after data loading 185 void checkNodeForExpand( const TreeItem * item, const QModelIndex &parent ); 186 void checkAllNodesForExpand(); 187 188 // Retrieve text data for indexes 189 QStringList getTextForIndexes( QModelIndexList const & idxList ) const; 190 191 // Delete items for indexes 192 void removeItemsForIndexes( QModelIndexList const & idxList ); 193 194 // Add new folder beside item and return its index 195 // or empty index if fail 196 QModelIndex addNewFolder( QModelIndex const & idx ); 197 198 // Add new headword to given folder 199 // return false if it already exists there 200 bool addNewHeadword( QString const & path, QString const & headword ); 201 202 // Remove headword from given folder 203 // return false if failed 204 bool removeHeadword( QString const & path, QString const & headword ); 205 206 // Return true if headwors is already presented in Favorites 207 bool isHeadwordPresent( QString const & path, QString const & headword ); 208 209 // Return path in the tree to item 210 QString pathToItem( QModelIndex const & idx ); 211 itemType(QModelIndex const & idx)212 TreeItem::Type itemType( QModelIndex const & idx ) 213 { return getItem( idx )->type(); } 214 215 // Export/import Favorites 216 void getDataInXml( QByteArray & dataStr ); 217 void getDataInPlainText( QString & dataStr ); 218 bool setDataFromXml( QString const & dataStr ); 219 220 void saveData(); 221 222 public slots: 223 void itemCollapsed ( const QModelIndex & index ); 224 void itemExpanded ( const QModelIndex & index ); 225 226 signals: 227 void expandItem( const QModelIndex & index ); 228 229 protected: 230 void readData(); 231 void addFolder( TreeItem * parent, QDomNode & node ); 232 void storeFolder( TreeItem * folder, QDomNode & node ); 233 234 // Find item in folder 235 QModelIndex findItemInFolder( QString const & itemName, int itemType, 236 QModelIndex const & parentIdx ); 237 238 TreeItem *getItem( const QModelIndex &index ) const; 239 240 // Find folder with given name or create it if folder not exist 241 QModelIndex forceFolder( QString const & name, QModelIndex const & parentIdx ); 242 243 // Add headword to given folder 244 // return false if such headwordalready exists 245 bool addHeadword( QString const & word, QModelIndex const & parentIdx ); 246 247 // Return tree level for item 248 int level( QModelIndex const & idx ); 249 250 private: 251 QString m_favoritesFilename; 252 TreeItem * rootItem; 253 QDomDocument dom; 254 bool dirty; 255 }; 256 257 #define FAVORITES_MIME_TYPE "application/x-goldendict-tree-items" 258 259 class FavoritesMimeData : public QMimeData 260 { 261 Q_OBJECT 262 public: FavoritesMimeData()263 FavoritesMimeData() : QMimeData() 264 {} 265 formats() const266 virtual QStringList formats() const 267 { return QStringList( QString::fromLatin1( FAVORITES_MIME_TYPE ) ); } 268 hasFormat(const QString & mimetype) const269 virtual bool hasFormat(const QString & mimetype) const 270 { return mimetype.compare( QString::fromLatin1( FAVORITES_MIME_TYPE ) ) == 0; } 271 setIndexesList(QModelIndexList const & list)272 void setIndexesList( QModelIndexList const & list ) 273 { indexes.clear(); indexes = list; } 274 getIndexesList() const275 QModelIndexList const & getIndexesList() const 276 { return indexes; } 277 278 private: 279 QStringList mimeFormats; 280 QModelIndexList indexes; 281 }; 282 283 #endif // __FAVORITIESPANEWIDGET_HH__INCLUDED__ 284