├── ABOUT ├── LICENSE ├── Manifest.txt ├── MiniCopier.sh ├── README.md ├── build.xml ├── lib └── PgsLookAndFeel.jar └── src ├── img ├── alt │ ├── cancel.png │ ├── down.png │ ├── first.png │ ├── last.png │ └── up.png ├── basket.png ├── delete.gif ├── down.gif ├── failed.gif ├── first.gif ├── icon.gif ├── icon.ico ├── icon.jpg ├── icon.png ├── last.gif ├── list.png ├── minicopier-logo.png ├── oldtheme │ ├── credits.png │ ├── delete.png │ ├── down.png │ ├── first.png │ ├── last.png │ ├── list.png │ ├── options.png │ └── up.png ├── options.png ├── paste.png ├── retry.gif └── up.gif └── minicopier ├── Basket.java ├── Configuration.java ├── Copier.java ├── FailedQueue.java ├── FileToTransfer.java ├── MainQueue.java ├── ThroughputLimitInputStream.java ├── TransferTask.java ├── configuration.ini ├── gui ├── Credits.java ├── DialogMsg.java ├── FailedPanel.java ├── MainFrame.java ├── OptionsPanel.java ├── QueueJButton.java ├── SupPanel.java └── TransfersPanel.java └── i18n ├── Language.java ├── minicopier.properties ├── minicopier_en.properties └── minicopier_fr.properties /ABOUT: -------------------------------------------------------------------------------- 1 | MiniCopier 0.5 2 | May 2009 3 | Adrian Courrèges 4 | 5 | PROJECT PAGE : 6 | ============== 7 | http://www.adriancourreges.com/projects/minicopier/ 8 | 9 | 10 | DESCRIPTION: 11 | ============ 12 | 13 | MiniCopier intends to improve graphic copy/paste file operations on some popular OSes. 14 | Its features are closed to the ones of SuperCopier (Windows environment). 15 | It lets you create a queue of transfers, so only a file is copied at a time. 16 | You can manage the queue by changing the position of any pending transfer. 17 | It also handles pause and resume operations. 18 | If a transfer fails, the bytes already copied are not erased, so MiniCopier 19 | can resume the transfer for you later. 20 | All the operations are done by "drag-and-drops" on the icons. 21 | MiniCopier is published under the GNU GPL. 22 | 23 | 24 | REQUIREMENTS : 25 | ============== 26 | Unix system with: GNOME/KDE/XFCE 27 | or Windows or Mac OS X 28 | Java virtual machine 1.5 (or more recent) 29 | 30 | 31 | INSTALLATION: 32 | ============= 33 | Nothing to install. 34 | (Except Sun JRE 5.0 or more recent) 35 | 36 | 37 | RUN: 38 | ==== 39 | Just launch the MiniCopier.sh script. 40 | 41 | /!\ If you have Beryl/Compiz enabled, you might get a blank windows. 42 | For a fix, you can try to add the line below in MiniCopier.sh 43 | 44 | export AWT_TOOLKIT="MToolkit" 45 | 46 | just before the line: java -jar MiniCopier.jar $* 47 | 48 | Options: 49 | 50 | See configuration.ini (generated the fist time you launch MiniCopier) for 51 | more options. 52 | 53 | 54 | USE: 55 | ==== 56 | 57 | Drag and drop files or folder you wish to copy on the basket icon. 58 | Once you're done with filling the basket, drag and drop a destination folder 59 | to the box icon. All the content of the basket will be copied to that directory. 60 | 61 | LICENSE: 62 | ======== 63 | 64 | MiniCopier is free software released under the GNU General Public License (GPL). 65 | The software is also distributed with the PgsLookAndFeel library, (Apache Software 66 | License, see https://pgslookandfeel.dev.java.net). 67 | 68 | 69 | CONTACT: 70 | ======== 71 | 72 | If you want to send me bug reports, suggestions, or just tell what you think 73 | of this software: www.adriancourreges.com/about/ 74 | 75 | 76 | CHANGELOG: 77 | ========== 78 | 79 | v0.5 80 | Now support transfer speed limit. 81 | Displays current transfer speed. 82 | Displays remaining time for current file and main queue. 83 | Several bugs fixed. 84 | 85 | v0.4 86 | As GTK support for swing applications suffers from many problems (combo box bug crashes 87 | the process, plus some graphic issues), MiniCopier now uses the Pagosoft library. 88 | default look'n'feel : pgs 89 | the option -nolnf is removed (edit configuration.ini for look'n'feel settings) 90 | 91 | v0.3 92 | new Panel to manage the failed transfers (retry, clear) 93 | language support : i18n with French and English 94 | Windows compatibility 95 | config file auto-generated 96 | multiselection in tables 97 | source code published under GPL 98 | new icons 99 | "Credits" dialog updated 100 | Some minor bugs correction 101 | 102 | v0.2: 103 | if possible, host system look'n'feel is used by default (Gnome) (disable with "-nolnf"). 104 | ability to rename the target of a transfer (if collision). 105 | ability to follow or ignore symbolic links. 106 | new panel for setting options. 107 | user can define a default action (for collision and links). 108 | the number of items inside the basket is displayed. 109 | sizes of total queue and current file are displayed. 110 | transfers list now displays size of each transfer and the destination folder. 111 | change of some strings in dialog boxes. 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | Main-Class: minicopier.Copier 2 | Class-Path: lib/PgsLookAndFeel.jar 3 | 4 | -------------------------------------------------------------------------------- /MiniCopier.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Launching MiniCopier..." 4 | cd `dirname $0` 5 | java -jar MiniCopier.jar $* 6 | echo "MiniCopier terminated." 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MiniCopier 2 | 3 | ### [Website](http://www.adriancourreges.com/projects/minicopier/)    [Download](http://www.adriancourreges.com/projects/minicopier/#dl-section)     4 | 5 | MiniCopier is a graphical copy manager. It provides more comfort and control over file copy operations than basic OS functions. 6 | You can use it to queue several transfers, resume a copy which has failed, limit the speed or pause the copy... 7 | MiniCopier is multiplatform and supports Linux, Windows and MacOS X systems. 8 | 9 | ![screenshot-1](http://www.adriancourreges.com/projects/minicopier/minicopier-0.5-screen2.png) 10 | 11 | ## Features 12 | 13 | * Pause a copy 14 | * Treatment of the transfers one after the other 15 | * Add new transfers to the queue while a copy is already being processed 16 | * Dynamic management of the queue of remaining transfers 17 | * Limit the speed of the copy 18 | * Skip current transfer to proceed to the next one 19 | * Resume a copy at the exact point where it failed (no need to start over) 20 | * Choose another name for the target if a file already exists 21 | * Can follow or ignore symbolic links (Unix systems only) 22 | * Set a default behavior if target file already exists 23 | * Keep track of the transfers which failed. 24 | 25 | 26 | ## Requirements 27 | 28 | Java should be installed. (JRE 5.0 or later) 29 | 30 | ## License 31 | 32 | MiniCopier is published under the GNU GPLv2 license. 33 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /lib/PgsLookAndFeel.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/lib/PgsLookAndFeel.jar -------------------------------------------------------------------------------- /src/img/alt/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/alt/cancel.png -------------------------------------------------------------------------------- /src/img/alt/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/alt/down.png -------------------------------------------------------------------------------- /src/img/alt/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/alt/first.png -------------------------------------------------------------------------------- /src/img/alt/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/alt/last.png -------------------------------------------------------------------------------- /src/img/alt/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/alt/up.png -------------------------------------------------------------------------------- /src/img/basket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/basket.png -------------------------------------------------------------------------------- /src/img/delete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/delete.gif -------------------------------------------------------------------------------- /src/img/down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/down.gif -------------------------------------------------------------------------------- /src/img/failed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/failed.gif -------------------------------------------------------------------------------- /src/img/first.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/first.gif -------------------------------------------------------------------------------- /src/img/icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/icon.gif -------------------------------------------------------------------------------- /src/img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/icon.ico -------------------------------------------------------------------------------- /src/img/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/icon.jpg -------------------------------------------------------------------------------- /src/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/icon.png -------------------------------------------------------------------------------- /src/img/last.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/last.gif -------------------------------------------------------------------------------- /src/img/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/list.png -------------------------------------------------------------------------------- /src/img/minicopier-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/minicopier-logo.png -------------------------------------------------------------------------------- /src/img/oldtheme/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/credits.png -------------------------------------------------------------------------------- /src/img/oldtheme/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/delete.png -------------------------------------------------------------------------------- /src/img/oldtheme/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/down.png -------------------------------------------------------------------------------- /src/img/oldtheme/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/first.png -------------------------------------------------------------------------------- /src/img/oldtheme/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/last.png -------------------------------------------------------------------------------- /src/img/oldtheme/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/list.png -------------------------------------------------------------------------------- /src/img/oldtheme/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/options.png -------------------------------------------------------------------------------- /src/img/oldtheme/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/oldtheme/up.png -------------------------------------------------------------------------------- /src/img/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/options.png -------------------------------------------------------------------------------- /src/img/paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/paste.png -------------------------------------------------------------------------------- /src/img/retry.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/retry.gif -------------------------------------------------------------------------------- /src/img/up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/img/up.gif -------------------------------------------------------------------------------- /src/minicopier/Basket.java: -------------------------------------------------------------------------------- 1 | /* 2 | Basket.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | import java.util.*; 22 | 23 | public class Basket { 24 | 25 | //Contains paths of files/folders to be copied 26 | private Vector basketContent; 27 | 28 | /* Creation of an empty basket */ 29 | public Basket () { 30 | this.basketContent = new Vector() ; 31 | } 32 | 33 | /* Add a path to the basket 34 | * @path path of a folder/file to be copied 35 | */ 36 | public void add (String path) { 37 | this.basketContent.add(path); 38 | } 39 | 40 | public Iterator getIterator() { 41 | return basketContent.iterator(); 42 | } 43 | 44 | public boolean isEmpty() { 45 | return this.basketContent.isEmpty(); 46 | } 47 | 48 | public int getLength(){ 49 | return basketContent.size(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/minicopier/Configuration.java: -------------------------------------------------------------------------------- 1 | /* 2 | Configuration.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | 22 | import java.util.*; 23 | import java.io.*; 24 | 25 | import minicopier.gui.DialogMsg; 26 | 27 | public class Configuration { 28 | 29 | private static final String configName = "configuration.ini"; 30 | 31 | public static String language; 32 | 33 | public static boolean alwaysOnTop; 34 | 35 | //Look And Feel 36 | //"pgs" (default) 37 | //"native" 38 | //"metal" 39 | public static String lookAndFeel; 40 | 41 | //What to do if destination file already exists 42 | // 0 -> ask user 43 | // 1 -> ignore 44 | // 2 -> overwrite 45 | // 3 -> overwrite if older 46 | // 4 -> resume 47 | // 5 -> rename 48 | public static int collisionAction; 49 | 50 | //What to do if a source path contains a symbolic link 51 | //(Unix systems only) 52 | // 0 -> follow 53 | // 1 -> ignore 54 | public static int symbolicLinkAction; 55 | 56 | //Is speed limit active? 57 | public static boolean limitSpeed; 58 | 59 | //Maximum throughput of the transfer 60 | public static int nbBytesPerS; 61 | 62 | private static boolean firstLaunch = false; 63 | 64 | public Configuration(){ 65 | 66 | this.limitSpeed = false; 67 | 68 | this.nbBytesPerS = 1024*1024; 69 | 70 | Properties prop = new Properties(); 71 | 72 | File configFile = new File(configName); 73 | 74 | if (!configFile.exists()) { 75 | System.out.println("Configuration file not found. Creating configuration.ini."); 76 | createConfigFile(); 77 | firstLaunch = true; 78 | } 79 | 80 | try { 81 | FileInputStream in = new FileInputStream(configName); 82 | prop.load(in); 83 | in.close(); 84 | } catch (Exception e){ 85 | e.printStackTrace(); 86 | } 87 | 88 | setProp(prop); 89 | 90 | } 91 | 92 | public static void setProp(Properties prop){ 93 | 94 | String readProp; 95 | 96 | //Language 97 | readProp = prop.getProperty("language"); 98 | if (("").equals(readProp)||(readProp==null)){ 99 | language = "SystemLocale"; 100 | } else { 101 | language = readProp; 102 | } 103 | 104 | //Always on top 105 | readProp = prop.getProperty("alwaysontop"); 106 | if (("true").equals(readProp)){ 107 | alwaysOnTop = true; 108 | } else { 109 | alwaysOnTop = false; 110 | } 111 | 112 | //Look an Feel 113 | readProp = prop.getProperty("lnf"); 114 | if (("").equals(readProp)||(readProp==null)){ 115 | lookAndFeel = "pgs"; 116 | } 117 | else { 118 | lookAndFeel = readProp; 119 | } 120 | 121 | //Collision action 122 | readProp = prop.getProperty("collision"); 123 | if (("ask").equals(readProp)){ 124 | collisionAction = 0; 125 | } else if (("cancel").equals(readProp)){ 126 | collisionAction = 1; 127 | } else if (("overwrite").equals(readProp)){ 128 | collisionAction = 2; 129 | } else if (("overwrite_older").equals(readProp)){ 130 | collisionAction = 3; 131 | } else if (("resume").equals(readProp)){ 132 | collisionAction = 4; 133 | } else { 134 | collisionAction = 0; 135 | } 136 | 137 | //Symbolic links action 138 | readProp = prop.getProperty("symlinks"); 139 | if (("follow").equals(readProp)){ 140 | symbolicLinkAction = 0; 141 | } else if (("ignore").equals(readProp)){ 142 | symbolicLinkAction = 1; 143 | } else { 144 | symbolicLinkAction = 0; 145 | } 146 | 147 | } 148 | 149 | public final void createConfigFile(){ 150 | InputStreamReader isr=new InputStreamReader(getClass() 151 | .getClassLoader().getResourceAsStream("minicopier/configuration.ini")); 152 | 153 | BufferedReader buf = new BufferedReader(isr); 154 | 155 | PrintWriter writer; 156 | String toWrite; 157 | 158 | try { 159 | writer = new PrintWriter (new OutputStreamWriter (new FileOutputStream (configName))); 160 | while ((toWrite=buf.readLine())!=null){ 161 | writer.println(toWrite); 162 | } 163 | buf.close(); 164 | writer.close(); 165 | } catch (Exception e){ 166 | System.out.println("Error creation configuration file !"); 167 | } 168 | 169 | } 170 | 171 | public boolean wasFirstLaunch(){ 172 | return this.firstLaunch; 173 | } 174 | 175 | public synchronized static void setSpeedValue(int i){ 176 | Configuration.nbBytesPerS = i; 177 | } 178 | 179 | public synchronized static int getSpeedValue(){ 180 | return Configuration.nbBytesPerS; 181 | } 182 | 183 | 184 | 185 | 186 | 187 | } 188 | -------------------------------------------------------------------------------- /src/minicopier/Copier.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copier.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | 22 | import java.io.*; 23 | import java.net.*; 24 | import java.util.*; 25 | 26 | import minicopier.gui.DialogMsg; 27 | import minicopier.gui.MainFrame; 28 | import minicopier.i18n.Language; 29 | 30 | public class Copier { 31 | 32 | //Application name and version 33 | public static String name = "MiniCopier"; 34 | public static String version = "0.5"; 35 | 36 | //The basket contains string paths to the files added by a user 37 | //for a copy. A 'paste' will empty the basket by transferring items 38 | //to the main queue. 39 | private Basket basket; 40 | 41 | //The path of the file being copied 42 | private String currentFileSource; 43 | 44 | //The path of the destination file 45 | private String currentFileDestination; 46 | 47 | //True if the Copier is working on a copy 48 | private Boolean busy; 49 | 50 | //True if the Copier is paused 51 | private Boolean paused; 52 | 53 | //The main queue contains the remaining file-only transfers to be done. 54 | public static MainQueue mainQueue; 55 | 56 | //The failed items 57 | public static FailedQueue failedItems; 58 | 59 | //Thread copying a file 60 | private TransferTask copyOp; 61 | 62 | //Transfer sizes sum 63 | private long queueTotalSize; 64 | 65 | //Bytes already copied 66 | private long queueCurrentSize; 67 | 68 | //Current treated file total size 69 | private long fileTotalSize; 70 | 71 | //Bytes already copied for current file 72 | private long fileCurrentSize; 73 | 74 | //GUI of the copier 75 | private MainFrame gui; 76 | 77 | private long bytesCounter; 78 | 79 | 80 | 81 | /* Create a new Copier */ 82 | public Copier() { 83 | this.basket = new Basket(); 84 | this.mainQueue = new MainQueue(this); 85 | this.failedItems = new FailedQueue(this); 86 | this.busy = false; 87 | this.paused = false; 88 | this.copyOp = null; 89 | this.currentFileSource = ""; 90 | this.currentFileDestination = ""; 91 | this.queueTotalSize = 0; 92 | this.queueCurrentSize = 0; 93 | this.fileTotalSize = 0; 94 | this.fileCurrentSize = 0; 95 | this.gui = null; 96 | this.bytesCounter = 0; 97 | } 98 | 99 | 100 | /* Add a file/folder path to the basket 101 | * @param path path of the file or folder to be copied 102 | */ 103 | public void add2basket (String path) { 104 | this.basket.add(path); 105 | } 106 | 107 | public String getCurrentFileSource() { 108 | return this.currentFileSource; 109 | } 110 | 111 | public String getCurrentFileDestination() { 112 | return this.currentFileDestination; 113 | } 114 | 115 | private void setCurrentFileStrings(String sourcePath, String destPath) { 116 | this.currentFileSource = sourcePath; 117 | this.currentFileDestination = destPath; 118 | this.gui.changeCurrentFileSignal(); 119 | } 120 | 121 | public void setGui(MainFrame view){ 122 | this.gui = view; 123 | } 124 | 125 | public void setPause(boolean b){ 126 | this.paused = b; 127 | this.gui.changePauseStateSignal(b); 128 | } 129 | 130 | public boolean getPause(){ 131 | return this.paused; 132 | } 133 | 134 | public boolean getBusy(){ 135 | return this.busy; 136 | } 137 | 138 | 139 | public void skip(boolean b){ 140 | this.copyOp.setCancelAndQueue(b); 141 | } 142 | 143 | public void addURIString2basket (String uriString) { 144 | String file2add = this.stringURI2StringPath(uriString); 145 | if (file2add != null) { 146 | this.add2basket(file2add); 147 | } 148 | } 149 | 150 | public void paste2URIString(String uriString) { 151 | String folder2Paste = this.stringURI2StringPath(uriString); 152 | if (folder2Paste != null) { 153 | this.paste(folder2Paste); 154 | } 155 | } 156 | 157 | public String stringURI2StringPath (String uriString) { 158 | URI uri = null; 159 | try{ 160 | uri = new URI(uriString); 161 | } catch (URISyntaxException e){ 162 | System.err.println(uriString+" is not a valid URI."); 163 | } 164 | return (uri.getPath()); 165 | } 166 | /* Add a FileToTransfer to the main queue 167 | * @param transfer The file to be put into main queue 168 | */ 169 | public void addFile2Queue(FileToTransfer file){ 170 | 171 | this.mainQueue.addFile(file); 172 | //System.out.println("Transfer\n"+ file.getSourcePath() + "\nto folder " 173 | // + file.getDestinationFilePath() + "\nadded in queue. "); 174 | 175 | } 176 | 177 | /* Add the items of the folder in the queue */ 178 | public void addFolder2Queue(File parentFolder, String destinationFolder) { 179 | 180 | 181 | //Listing directory content 182 | File[] dirlist = parentFolder.listFiles(); 183 | 184 | File currentItem; 185 | FileToTransfer transfer; 186 | String newDestinationPath = ""; 187 | 188 | if (dirlist != null){ //input item is really a folder 189 | 190 | for ( int i = 0; i < dirlist.length; i++) { 191 | //Dealing with directory content 192 | 193 | currentItem = dirlist[i]; 194 | 195 | 196 | if (currentItem.isDirectory()) { 197 | 198 | newDestinationPath = destinationFolder + 199 | File.separator + parentFolder.getName(); 200 | //Recursive call on subfolder 201 | addFolder2Queue(currentItem, newDestinationPath); 202 | 203 | } else { //item is a file 204 | 205 | newDestinationPath = destinationFolder + 206 | File.separator + parentFolder.getName() ; 207 | 208 | transfer = new FileToTransfer(currentItem.getPath(), 209 | newDestinationPath); 210 | this.addFile2Queue(transfer); 211 | } 212 | } 213 | } else { 214 | System.err.println("Error reading directory : "+parentFolder); 215 | } 216 | } 217 | 218 | 219 | 220 | /** Transforms basket items into FileToTransfer (even directories 221 | * content) and transfer them to the main queue. 222 | * @param destinationPath The path to the directory in which basket 223 | * items must be copied. 224 | */ 225 | 226 | public void paste(String destinationPath) { 227 | 228 | System.out.println("Paste requested to : " + destinationPath); 229 | File destination = new File(destinationPath); 230 | if (!destination.isDirectory()) {return;} 231 | 232 | //If it is a new paste, we restart the queue stats 233 | if (!busy) { 234 | this.queueTotalSize = 0; 235 | this.queueCurrentSize = 0; 236 | } 237 | 238 | Basket basketBackup = this.basket ; 239 | this.basket = new Basket(); 240 | Iterator basketContent = basketBackup.getIterator(); 241 | 242 | String filePath; 243 | 244 | File item2add; 245 | 246 | while (basketContent.hasNext()) { 247 | filePath = basketContent.next(); 248 | 249 | item2add = new File(filePath); 250 | 251 | if ((Configuration.symbolicLinkAction == 0) || isNotLink(item2add)) { 252 | if (!item2add.isDirectory()) { //if the item is a file 253 | 254 | System.out.println("adding file to main queue"); 255 | addFile2Queue(new FileToTransfer(filePath,destinationPath)); 256 | 257 | } else { //the item is a folder 258 | //System.out.println("adding folder to main queue"); 259 | this.addFolder2Queue(item2add,destinationPath); 260 | } 261 | } 262 | } 263 | 264 | //We launch the treatment anyway, it will exit by 265 | //itself if necessary 266 | forceStart(); 267 | } 268 | 269 | public void forceStart(){ 270 | ForceTreatment t = new ForceTreatment(); 271 | t.start(); 272 | } 273 | 274 | public void treatQueue() { 275 | 276 | synchronized(this){ 277 | if (busy) {return;} //other instance running... 278 | 279 | this.busy = true; 280 | } 281 | 282 | boolean proceed = true; 283 | boolean append = false; 284 | 285 | 286 | FileToTransfer transfer; 287 | 288 | while (!this.mainQueue.isEmpty()) { 289 | 290 | //Pick & extract first transfer in queue 291 | synchronized (mainQueue) { 292 | transfer = mainQueue.extractFirst(); 293 | } 294 | 295 | this.setCurrentFileStrings(transfer.getSourcePath() 296 | ,transfer.getDestinationFilePath()); 297 | 298 | 299 | //default : we proceed to the copy without append 300 | proceed = true; 301 | append = false; 302 | 303 | //target already exists ? 304 | 305 | File destFile = transfer.getDestinationFile(); 306 | 307 | 308 | 309 | if (destFile.length() > 0) { //target exists 310 | 311 | boolean acceptableAction = false; 312 | 313 | int actionToDo = Configuration.collisionAction; 314 | 315 | while (!acceptableAction) { 316 | 317 | long sourceSize = transfer.getSourceFile().length(); 318 | long destSize = transfer.getDestinationFile().length(); 319 | 320 | switch (actionToDo) { 321 | 322 | case (0) : //ask 323 | int choice = DialogMsg.alreadyExistsChoice( 324 | transfer.getSourcePath(), 325 | sourceSize, 326 | transfer.getDestinationFilePath(), 327 | destSize); 328 | 329 | if (choice==0) { //overwrite 330 | actionToDo = 2; 331 | } 332 | 333 | if (choice==1) { //resume copy 334 | actionToDo = 4; 335 | } 336 | 337 | if (choice==2) { //Rename 338 | actionToDo = 5; 339 | } 340 | 341 | if (choice==3) { //cancel copy 342 | actionToDo = 1; 343 | } 344 | 345 | break; 346 | 347 | case (1) : //ignore 348 | proceed = false; 349 | acceptableAction = true; 350 | break; 351 | 352 | case (2) : //overwrite 353 | 354 | //We just make sure the source path is different 355 | //from the destination path. 356 | 357 | if (transfer.getSourcePath().equals(transfer.getDestinationFilePath())) { 358 | DialogMsg.errorOverwrite(); 359 | acceptableAction = false; 360 | actionToDo = 0; 361 | } else { 362 | //nothing to do : append==false proceed==true 363 | acceptableAction = true; 364 | } 365 | 366 | break; 367 | 368 | case (3): //overwrite if older 369 | proceed = (transfer.getSourceFile().lastModified() 370 | > destFile.lastModified()); 371 | acceptableAction = true; 372 | break; 373 | 374 | case (4) : //resume 375 | //dest file might be a different file but with the same name 376 | //as source. User wanted to resume, so we resume anyway, but 377 | //only if the size of file permit it. 378 | append = (destFile.length() <= transfer.getSize()); 379 | acceptableAction = true; 380 | 381 | 382 | break; 383 | 384 | case (5) : //rename 385 | 386 | String newName = DialogMsg.askNewName(transfer.getName()); 387 | 388 | boolean leaveRename = (newName==null); 389 | 390 | while (newName != null 391 | && (newName.equals(transfer.getName()) || !nameIsAcceptable(newName,transfer.getDestinationFolderPath()))) { 392 | //User confirms a new name 393 | DialogMsg.renameError(); 394 | newName = DialogMsg.askNewName(transfer.getName()); 395 | 396 | } 397 | 398 | if (newName != null) { 399 | //The name is correct, we can change destination path 400 | transfer.changeTargetName(newName); 401 | 402 | //The action will be acceptable if the file doesn't already 403 | //exists, else we ask what to do. 404 | acceptableAction = !(transfer.getDestinationFile().exists()); 405 | } else { //The user has canceled renaming 406 | acceptableAction = false; 407 | } 408 | 409 | actionToDo = 0; //we ask for a new choice 410 | 411 | 412 | break; 413 | 414 | default : break; 415 | 416 | } 417 | 418 | } 419 | 420 | 421 | } 422 | 423 | if (proceed) { //So we must proceed to the copy 424 | 425 | this.setCurrentFileStrings(transfer.getSourcePath() 426 | ,transfer.getDestinationFilePath()); 427 | 428 | //System.out.println("Treating " + transfer.getSourcePath()); 429 | //System.out.println("-> " + transfer.getDestinationFilePath()); 430 | 431 | //Creation of thread 432 | this.copyOp = new TransferTask(this,transfer,append); 433 | 434 | //System.out.println("Beginning transfer..."); 435 | copyOp.start(); 436 | 437 | //Waiting for transfer to finish 438 | try { 439 | copyOp.join(); 440 | } 441 | catch (Exception e) { 442 | System.out.println("Copy Thread Error " + e); 443 | } 444 | 445 | //System.out.println("Copy thread terminated"); 446 | //Transfer has ended (maybe not completed) 447 | if (!copyOp.getCompleted()) { //incomplete transfer 448 | System.out.println("Transfer NOT completed"); 449 | 450 | //Has it been canceled by a skip action ? 451 | if (copyOp.getCancel()) { 452 | System.out.println("(has been skipped)"); 453 | if (copyOp.getPutInQueue()) { //user wants to resume later 454 | mainQueue.addFile(transfer); 455 | } else { //user does not want to resume later 456 | //we add the transfer to the "failed items" list 457 | this.failedItems.addFile(transfer); 458 | } 459 | 460 | } else { //it's an IO exception 461 | System.out.println("(error occured)"); 462 | boolean ioPutInQueue = DialogMsg.transferErrorChoice(); 463 | if (ioPutInQueue) { 464 | //user wants to resume later 465 | mainQueue.addFile(transfer); 466 | } else { 467 | //transfer has failed 468 | this.failedItems.addFile(transfer); 469 | } 470 | 471 | } 472 | 473 | 474 | this.decreaseQueueTotalSize(this.fileTotalSize); 475 | this.decreaseQueueCurrentSize(this.fileCurrentSize); 476 | this.setFileCurrentSize(0); 477 | 478 | } 479 | this.copyOp = null; 480 | 481 | } else { //destination file already exists, and user canceled 482 | this.decreaseQueueTotalSize(transfer.getSize()); 483 | this.setFileTotalSize(0); 484 | this.setFileCurrentSize(0); 485 | this.failedItems.addFile(transfer); 486 | } 487 | 488 | } 489 | 490 | //MainQueue SEEMS to be empty... 491 | //Let's just check other transfers were not added after the test. 492 | 493 | synchronized(this){ 494 | busy=false; 495 | 496 | if (this.mainQueue.isEmpty()) { //empty, indeed 497 | this.setCurrentFileStrings("",""); 498 | return; 499 | } else { //still some transfers remaining 500 | //we launch the treatment once again 501 | forceStart(); 502 | return; 503 | } 504 | } 505 | 506 | } 507 | 508 | public void increaseQueueTotalSize(long nb) { 509 | this.queueTotalSize += nb; 510 | gui.totalSizeSignal(); 511 | } 512 | 513 | public void decreaseQueueTotalSize(long nb){ 514 | this.queueTotalSize -= nb; 515 | gui.totalSizeSignal(); 516 | } 517 | 518 | public long readAndInitBytesCounter(){ 519 | long result = this.bytesCounter; 520 | this.bytesCounter -= result; 521 | return result; 522 | } 523 | 524 | 525 | public void increaseQueueCurrentSize(long nb) { 526 | this.queueCurrentSize += nb; 527 | //For speed measures 528 | this.bytesCounter += nb; 529 | } 530 | 531 | public void decreaseQueueCurrentSize(long nb){ 532 | this.queueCurrentSize -= nb; 533 | } 534 | 535 | public void setFileCurrentSize(long s){ 536 | this.fileCurrentSize = s; 537 | } 538 | 539 | public void increaseFileCurrentSize(long nb) { 540 | this.fileCurrentSize += nb; 541 | increaseQueueCurrentSize(nb); 542 | } 543 | 544 | public void setFileTotalSize(long s) { 545 | this.fileTotalSize = s; 546 | gui.currentSizeSignal(); 547 | } 548 | 549 | public long getTotalBytesRemaining(){ 550 | return this.queueTotalSize - this.queueCurrentSize; 551 | } 552 | 553 | public long getCurrentBytesRemaining(){ 554 | return this.fileTotalSize - this.fileCurrentSize; 555 | } 556 | 557 | public int getTotalPercent() { 558 | int result = 0; 559 | if (this.queueTotalSize != 0) { 560 | Double tmp = (((double)this.queueCurrentSize)/((double)this.queueTotalSize)*100); 561 | result = tmp.intValue(); 562 | } 563 | return result; 564 | } 565 | 566 | public int getCurrentPercent() { 567 | int result = 0; 568 | if (this.fileTotalSize != 0) { 569 | Double tmp =((double)this.fileCurrentSize)/((double)this.fileTotalSize)*100; 570 | result = tmp.intValue(); 571 | } 572 | return result; 573 | } 574 | 575 | public long getQueueTotalSize() { 576 | return this.queueTotalSize; 577 | } 578 | 579 | public long getFileTotalSize() { 580 | return this.fileTotalSize; 581 | } 582 | 583 | public boolean pause() { 584 | if (this.copyOp != null) { 585 | this.copyOp.setPause(); 586 | return true; 587 | } else { 588 | return false; 589 | } 590 | } 591 | 592 | public void unpause() { 593 | if (this.copyOp != null) { 594 | this.copyOp.unpause(); 595 | } 596 | } 597 | 598 | public int basketLength(){ 599 | return this.basket.getLength(); 600 | } 601 | 602 | public void clearBasket() { 603 | this.basket = new Basket(); 604 | } 605 | 606 | 607 | /** Depending on platform, some characters in file's name are 608 | * forbidden. So we just create a temp file and try to rename 609 | * it to know if the name is accepted by the host OS. 610 | * @param fileName new name the user wants to use 611 | * @param dirPath the destination directory path 612 | */ 613 | public boolean nameIsAcceptable(String fileName,String dirPath){ 614 | 615 | boolean result = false; 616 | 617 | try { 618 | 619 | File temp = File.createTempFile("MiniCopier",".tmp"); 620 | 621 | String newPath = temp.getParentFile().getAbsolutePath()+ 622 | File.separator + fileName; 623 | 624 | File newFile = new File(newPath); 625 | 626 | if (temp.renameTo(newFile)) { 627 | result = true; //name is correct for the OS 628 | } 629 | 630 | temp.delete(); 631 | newFile.delete(); 632 | 633 | } catch (Exception e) { 634 | e.printStackTrace(); 635 | } 636 | 637 | //Just making sure the new target isn't a directory 638 | if (result) { 639 | File dirCheck = new File(dirPath + File.separator + fileName); 640 | if (dirCheck.isDirectory()) result = false; 641 | } 642 | 643 | return result; 644 | } 645 | 646 | public static boolean isNotLink(File file) 647 | { 648 | try { 649 | if (!file.exists()) 650 | return true; 651 | else 652 | { 653 | String canonpath = file.getCanonicalPath(); 654 | //System.out.println(canonpath); 655 | String abspath = file.getAbsolutePath(); 656 | //System.out.println(abspath); 657 | return abspath.equals(canonpath); 658 | } 659 | } 660 | catch(IOException ex) { 661 | System.err.println(ex); 662 | return true; 663 | } 664 | } 665 | 666 | /** 667 | * @param args 668 | */ 669 | public static void main(String[] args) { 670 | 671 | //Initialization 672 | Configuration conf = new Configuration(); 673 | Language.init(Configuration.language); 674 | 675 | for (String arg : args) { 676 | //deprecated 677 | //if (arg.equals("-nolnf")) Configuration.nativeLnF = false; 678 | if (arg.equals("-nolnf")) System.out.println("-nolnf : Option no longer available! \n" + 679 | "Please edit \"configuration.ini\" to set the look and feel."); 680 | } 681 | 682 | Copier copier = new Copier(); 683 | MainFrame frame = new MainFrame(copier); 684 | 685 | //Display a welcome dialog to the user for the first launch 686 | if (conf.wasFirstLaunch()) DialogMsg.displayWelcome(); 687 | 688 | frame.setAlwaysOnTop(Configuration.alwaysOnTop); 689 | 690 | } 691 | 692 | 693 | private class ForceTreatment extends Thread { 694 | public void run() { 695 | treatQueue(); 696 | } 697 | } 698 | } 699 | 700 | 701 | -------------------------------------------------------------------------------- /src/minicopier/FailedQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | FailedQueue.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | 22 | import java.util.Vector; 23 | 24 | import javax.swing.table.DefaultTableModel; 25 | import minicopier.gui.DialogMsg; 26 | import minicopier.i18n.Language; 27 | 28 | public class FailedQueue { 29 | 30 | private Copier copier; 31 | 32 | private Vector failedItems; 33 | private DefaultTableModel tableModel; 34 | 35 | 36 | public FailedQueue(Copier c) { 37 | this.copier = c; 38 | this.failedItems = new Vector(); 39 | 40 | String[] columnsNames = {Language.get("MainFrame.TransfersPane.sourceRow"), 41 | Language.get("MainFrame.TransfersPane.sizeRow"), 42 | Language.get("MainFrame.TransfersPane.destinationRow")}; 43 | this.tableModel = new FailedModel(columnsNames,0); 44 | } 45 | 46 | public DefaultTableModel getTableModel() { 47 | return this.tableModel; 48 | } 49 | 50 | 51 | public synchronized boolean isEmpty(){ 52 | return this.failedItems.isEmpty(); 53 | } 54 | 55 | 56 | public synchronized void addFile(FileToTransfer file){ 57 | this.failedItems.add(file); 58 | String[] data = {file.getSourcePath(), 59 | DialogMsg.prettySize(file.getSize()), 60 | file.getDestinationFolderPath() 61 | }; 62 | this.tableModel.addRow(data); 63 | } 64 | 65 | public int[] remove(int i[]) { 66 | 67 | int[] result = {-1,-1}; 68 | int length = i.length; 69 | 70 | int k = 0; 71 | int ind; 72 | int del = 0; 73 | 74 | for (k=0; k<=length-1; k++){ 75 | ind = i[k] - del; 76 | this.failedItems.removeElementAt(ind); 77 | this.tableModel.removeRow(ind); 78 | del++; 79 | } 80 | return result; 81 | } 82 | 83 | public int[] retry(int i[]) { 84 | 85 | int[] result = {-1,-1}; 86 | int length = i.length; 87 | 88 | int k = 0; 89 | int ind; 90 | int del = 0; 91 | 92 | for (k=0; k<=length-1; k++){ 93 | ind = i[k] - del; 94 | copier.addFile2Queue(this.failedItems.get(ind)); 95 | this.failedItems.removeElementAt(ind); 96 | this.tableModel.removeRow(ind); 97 | del++; 98 | } 99 | 100 | copier.forceStart(); 101 | return result; 102 | } 103 | 104 | 105 | 106 | 107 | private class FailedModel extends DefaultTableModel{ 108 | 109 | public FailedModel(Object[] s,int i){ 110 | super(s,i); 111 | } 112 | 113 | public boolean isCellEditable(int row, int column) { 114 | return false; 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/minicopier/FileToTransfer.java: -------------------------------------------------------------------------------- 1 | /* 2 | FileToTransfer.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | import java.io.*; 22 | 23 | /** FileToTransfer represents a tranfer requested by the user. 24 | * It contains all the informations about the source file, and where 25 | * it must be copied, according to the user. 26 | */ 27 | 28 | public class FileToTransfer { 29 | 30 | //Source file path 31 | private String sourcePath; 32 | 33 | //File's copy destination path (folder) 34 | private String destinationPath; 35 | 36 | //Destination File Path 37 | private String destinationFilePath; 38 | 39 | //Name of source file 40 | private String name; 41 | 42 | //Size of source file 43 | private long size; 44 | 45 | /** Creation of a FileToTransfer 46 | * @param _path2source system path to the source file 47 | * @param _path2destinationfolder system path to the destination folder 48 | */ 49 | public FileToTransfer(String _path2source, 50 | String _path2destinationfolder) { 51 | 52 | //Using the argument Strings directly work, but the 53 | //display is not fine for Windows, so we create Files 54 | //and get the path (OS-dependent). 55 | 56 | //this.sourcePath = _path2source; 57 | 58 | File sourceFile = new File(_path2source); 59 | 60 | this.sourcePath = sourceFile.getPath(); 61 | this.name = sourceFile.getName(); 62 | this.size = sourceFile.length(); 63 | 64 | //this.destinationPath = _path2destinationfolder; 65 | 66 | 67 | File destFolder = new File(_path2destinationfolder); 68 | this.destinationPath = destFolder.getPath(); 69 | 70 | this.destinationFilePath = this.destinationPath 71 | + File.separator + this.name; 72 | 73 | 74 | } 75 | 76 | public String getSourcePath() { 77 | return this.sourcePath; 78 | } 79 | 80 | public File getSourceFile() { 81 | return new File(this.sourcePath); 82 | } 83 | 84 | public String getDestinationFolderPath() { 85 | return this.destinationPath; 86 | } 87 | 88 | public File getDestinationFolder() { 89 | return new File(this.getDestinationFolderPath()); 90 | } 91 | 92 | public String getDestinationFilePath() { 93 | return this.destinationFilePath; 94 | 95 | } 96 | 97 | public File getDestinationFile() { 98 | return new File(this.getDestinationFilePath()); 99 | } 100 | 101 | public String getName() { 102 | return this.name; 103 | } 104 | 105 | public long getSize() { 106 | return this.size; 107 | } 108 | 109 | public void changeTargetName(String newName){ 110 | this.destinationFilePath = this.destinationPath + File.separator + 111 | newName; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/minicopier/MainQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | MainQueue.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | 22 | 23 | import java.util.Vector; 24 | import javax.swing.table.*; 25 | 26 | import minicopier.gui.DialogMsg; 27 | 28 | import minicopier.i18n.Language; 29 | 30 | public class MainQueue { 31 | 32 | private Copier copier; 33 | 34 | private Vector mainQueue; 35 | 36 | private DefaultTableModel tableModel; 37 | 38 | 39 | public MainQueue(Copier c) { 40 | this.copier = c; 41 | this.mainQueue = new Vector(); 42 | 43 | String[] columnsNames = {Language.get("MainFrame.TransfersPane.sourceRow"), 44 | Language.get("MainFrame.TransfersPane.sizeRow"), 45 | Language.get("MainFrame.TransfersPane.destinationRow")}; 46 | this.tableModel = new TransfersModel(columnsNames,0); 47 | } 48 | 49 | public synchronized void addFile(FileToTransfer file){ 50 | this.mainQueue.add(file); 51 | String[] data = {file.getSourcePath(), 52 | DialogMsg.prettySize(file.getSize()), 53 | file.getDestinationFolderPath() 54 | }; 55 | this.tableModel.addRow(data); 56 | this.copier.increaseQueueTotalSize(file.getSize()); 57 | } 58 | 59 | public DefaultTableModel getTableModel() { 60 | return this.tableModel; 61 | } 62 | 63 | /** Remove and send the first element in queue */ 64 | public synchronized FileToTransfer extractFirst(){ 65 | FileToTransfer first = this.mainQueue.firstElement(); 66 | this.mainQueue.remove(0); 67 | this.tableModel.removeRow(0); 68 | return first; 69 | } 70 | 71 | public synchronized boolean isEmpty(){ 72 | return this.mainQueue.isEmpty(); 73 | } 74 | 75 | public int[] putFirst(int[] i){ 76 | int[] result = {-1,-1}; 77 | int length = i.length; 78 | int k = length-1; 79 | int ind; 80 | int del = 0; 81 | 82 | for (k=length-1; k>=0; k--){ 83 | ind = i[k] + del; 84 | this.mainQueue.add(0,mainQueue.elementAt(ind)); 85 | this.mainQueue.remove(ind+1); 86 | this.tableModel.moveRow(ind,ind,0); 87 | del++; 88 | } 89 | result[0] = 0; 90 | result[1] = length-1; 91 | 92 | /* 93 | if (i < mainQueue.size() && i >= 0) { 94 | this.mainQueue.add(0,mainQueue.elementAt(i)); 95 | this.tableModel.insertRow(0,(Vector)tableModel.getDataVector().elementAt(i)); 96 | this.mainQueue.remove(i+1); 97 | this.tableModel.removeRow(i+1); 98 | result = 0; 99 | } 100 | //System.out.println("Sortie putFirst"); 101 | * 102 | */ 103 | return result; 104 | } 105 | 106 | public int[] putLast(int i[]){ 107 | 108 | int[] result = {-1,-1}; 109 | int length = i.length; 110 | int k = 0; 111 | int ind; 112 | int del = 0; 113 | 114 | for (k=0; k<=length-1; k++){ 115 | ind = i[k] - del; 116 | this.mainQueue.add(mainQueue.elementAt(ind)); 117 | this.mainQueue.remove(ind); 118 | this.tableModel.addRow((Vector)tableModel.getDataVector().elementAt(ind)); 119 | this.tableModel.removeRow(ind); 120 | del++; 121 | } 122 | 123 | result[1] = tableModel.getRowCount()-1; 124 | result[0] = result[1]-(length-1); 125 | 126 | /* 127 | int result = -1; 128 | if (i < mainQueue.size() && i >= 0) { 129 | this.mainQueue.add(mainQueue.elementAt(i)); 130 | this.tableModel.addRow((Vector)tableModel.getDataVector().elementAt(i)); 131 | this.mainQueue.removeElementAt(i); 132 | this.tableModel.removeRow(i); 133 | result = (tableModel.getRowCount()-1); 134 | } 135 | */ 136 | 137 | return result; 138 | } 139 | 140 | public int[] putUp(int[] i) { 141 | 142 | int[] result = {-1,-1}; 143 | int length = i.length; 144 | int start = i[0]; 145 | 146 | int k = length-1; 147 | int ind; 148 | //we usually start inserting at "start-1" except when 149 | //start==0 (first element selected) 150 | int toInsert = (start == 0 ? 0 : start-1); 151 | int del = 0; 152 | 153 | for (k=length-1; k>=0; k--){ 154 | ind = i[k] + del; 155 | this.mainQueue.add(toInsert,mainQueue.elementAt(ind)); 156 | this.mainQueue.remove(ind+1); 157 | this.tableModel.moveRow(ind,ind,toInsert); 158 | del++; 159 | } 160 | 161 | result[0]=toInsert; 162 | result[1]=toInsert+length-1; 163 | 164 | /* 165 | int result = -1; 166 | //we do it for all, except for the first one 167 | if (i < mainQueue.size() || i > 0) { 168 | FileToTransfer f = mainQueue.elementAt(i-1); 169 | mainQueue.setElementAt(mainQueue.elementAt(i),i-1); 170 | mainQueue.setElementAt(f,i); 171 | tableModel.moveRow(i,i,i-1); 172 | 173 | result = i-1; 174 | } 175 | */ 176 | 177 | return result; 178 | } 179 | 180 | public int[] putDown(int i[]) { 181 | 182 | int[] result = {-1,-1}; 183 | int length = i.length; 184 | int last = i[length-1]; 185 | 186 | int k = 0; 187 | int ind; 188 | 189 | //we usually start inserting at "last+2" except when 190 | //last==length-1 (last element selected) 191 | int toInsert = (last == mainQueue.size()-1 ? mainQueue.size() : last+2); 192 | int del =0; 193 | 194 | for (k=0; k<=length-1; k++){ 195 | ind = i[k] - del; 196 | this.mainQueue.add(toInsert,mainQueue.elementAt(ind)); 197 | this.mainQueue.remove(ind); 198 | this.tableModel.moveRow(ind,ind,toInsert-1); 199 | del++; 200 | } 201 | 202 | result[1] = toInsert-1; 203 | result[0] = result[1]-(length-1); 204 | 205 | 206 | /* 207 | int result = -1; 208 | //don't consider the last one 209 | if (i < (mainQueue.size()-1) || i >= 0) { 210 | FileToTransfer f = mainQueue.elementAt(i+1); 211 | mainQueue.setElementAt(mainQueue.elementAt(i),i+1); 212 | mainQueue.setElementAt(f,i); 213 | tableModel.moveRow(i,i,i+1); 214 | 215 | result = i+1; 216 | }*/ 217 | 218 | return result; 219 | } 220 | 221 | public int[] remove(int i[]) { 222 | 223 | int[] result = {-1,-1}; 224 | int length = i.length; 225 | 226 | int k = 0; 227 | int ind; 228 | int del = 0; 229 | 230 | for (k=0; k<=length-1; k++){ 231 | ind = i[k] - del; 232 | this.copier.decreaseQueueTotalSize(mainQueue.elementAt(ind).getSize()); 233 | this.mainQueue.removeElementAt(ind); 234 | this.tableModel.removeRow(ind); 235 | del++; 236 | } 237 | 238 | 239 | /* 240 | int result = -1; 241 | if (i < mainQueue.size() && i >= 0) { 242 | this.copier.decreaseQueueTotalSize(mainQueue.elementAt(i).getSize()); 243 | this.mainQueue.removeElementAt(i); 244 | this.tableModel.removeRow(i); 245 | result = i; 246 | }*/ 247 | 248 | 249 | return result; 250 | } 251 | 252 | public class TransfersModel extends DefaultTableModel{ 253 | 254 | public TransfersModel(Object[] s,int i){ 255 | super(s,i); 256 | } 257 | 258 | public boolean isCellEditable(int row, int column) { 259 | return false; 260 | } 261 | 262 | } 263 | 264 | } 265 | -------------------------------------------------------------------------------- /src/minicopier/ThroughputLimitInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | ThroughputLimitInputStream.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | /* 21 | * This file is adapted from the one of muCommander, http://www.mucommander.com 22 | * Copyright (C) 2002-2008 Maxence Bernard 23 | */ 24 | 25 | package minicopier; 26 | 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | 30 | /** 31 | * ThroughputLimitInputStream extends InputStream to provide control over the transfer speed and limit it to a specified 32 | * number of bytes per second. 33 | * Whenever the bytes per second quota has been reached, the read and skip methods will lock and won't return 34 | * until either: 35 | *
    a new second commences, bringing the bytes read count back to zero for the new second 36 | *
  • {@link #setThroughputLimit(long)} is called with a more permissive bytes per second value (different from 0), 37 | * yielding to more bytes available for the current second. 38 | * 39 | *

    Setting the throughput limit to 0 effectively blocks all read and skip calls indefinitely. 40 | * Any calls to the read or skip methods will lock, the only way to remove this lock being to call the 41 | * {@link #setThroughputLimit(long)} method with a value different from 0 from another thread. 42 | * 43 | *

    Setting the throughput limit to -1 or any other negative values will disable any limit and make 44 | * this ThroughputLimitInputStream behave just like a normal InputStream. 45 | * 46 | *

    Finally, the {@link #setUnderlyingInputStream(java.io.InputStream)} method allows to use the 47 | * same ThroughputLimitInputStream instance for multiple InputStream instances, keeping the bytes count for the 48 | * current second intact and thus the throughput limit stable. This does not hold true if a new ThroughputLimitInputStream 49 | * is created for each InputStream, the bytes count for the current second starting at 0. 50 | * 51 | * @author Maxence Bernard 52 | */ 53 | public class ThroughputLimitInputStream extends InputStream { 54 | 55 | /** Underlying InputStream */ 56 | private InputStream in; 57 | 58 | 59 | /** Holds the current second, allowing to detect when a new second commences */ 60 | private long currentSecond; 61 | 62 | /** Number of bytes that have been read or skipped this second */ 63 | private long nbBytesReadThisSecond; 64 | 65 | 66 | /** 67 | * Creates a new ThroughputLimitInputStream with no initial throughput limit (-1 value). 68 | * 69 | * @param in underlying stream that is used to read data from 70 | */ 71 | public ThroughputLimitInputStream(InputStream in) { 72 | this.in = in; 73 | } 74 | 75 | /** 76 | * Creates a new ThroughputLimitInputStream with an initial throughput limit. 77 | * 78 | * @param in underlying stream that is used to read data from 79 | * @param bytesPerSecond initial throughput limit in bytes per second 80 | * @see #setThroughputLimit(long) 81 | */ 82 | public ThroughputLimitInputStream(InputStream in, long bytesPerSecond) { 83 | this.in = in; 84 | } 85 | 86 | 87 | /** 88 | * Changes the underlying InputStream which data is read from, keeping the bytes count for the current second intact. 89 | * 90 | *

    Note: the existing underlying InputStream will not be closed, the {@link #close()} method must be called prior 91 | * to calling this method. 92 | * 93 | * @param in the new InputStream to read data from 94 | */ 95 | public void setUnderlyingInputStream(InputStream in) { 96 | this.in = in; 97 | } 98 | 99 | 100 | /** 101 | * Returns the number of bytes that can be read (or skipped) without exceeding the current throughput limit. 102 | * This method blocks until at least 1 byte is available. In other words the method always returns 103 | * strictly positive values. 104 | * 105 | *

    If the current throughput limit is negative (no limit), this method returns immediately Integer.MAX_VALUE. 106 | *

    If the byte quota for the current second has been exceeded, this method locks and returns as soon as a new second 107 | * has started (i.e. bytes are available), or the {@link #setThroughputLimit(long)} with a more permissive value 108 | * has been called. 109 | *

    If the current throughput limit is 0, it will lock undefinitely, until {@link #setThroughputLimit(long)} has 110 | * been called from another thread with a value different from 0. 111 | * 112 | * @return the number of bytes available for reading without exceeding the current throughput limit 113 | */ 114 | private int getNbAllowedBytes() { 115 | 116 | // Update limit counter and retrieve number of milliseconds until next second 117 | long msUntilNextSecond = updateLimitCounter(); 118 | 119 | long allowedBytes; 120 | 121 | long bpsLimit = Configuration.getSpeedValue(); 122 | 123 | synchronized(this) { 124 | // Loop while throughput limit has been exceeded 125 | while((allowedBytes=bpsLimit- nbBytesReadThisSecond)<=0) { 126 | // Throughput limit was removed, return max int value 127 | if(bpsLimit<0) 128 | return Integer.MAX_VALUE; 129 | 130 | try { 131 | // If limit is 0, wait indefinitely for a call to notify() from setThroughputLimit() 132 | if(bpsLimit==0) 133 | wait(); 134 | // Wait until the current second is over for more bytes to be available, 135 | // or until a call to notify() is made from setThroughputLimit() 136 | else { 137 | wait(msUntilNextSecond); 138 | } 139 | } 140 | catch(InterruptedException e) { 141 | // No problem in this unlikely event, loop one more time and wait some more 142 | } 143 | 144 | // Update limit counter and retrieve number of milliseconds until next second 145 | msUntilNextSecond = updateLimitCounter(); 146 | } 147 | } 148 | 149 | return (int)allowedBytes; 150 | } 151 | 152 | 153 | /** 154 | * Checks if the current second has changed. If that's the case, updates the current second value and resets the 155 | * number of bytes read this second. Returns the number of milliseconds until a new second starts. 156 | */ 157 | private long updateLimitCounter() { 158 | long now = System.currentTimeMillis(); 159 | long nowSecond = now/1000; 160 | 161 | // Current second has changed 162 | if(this.currentSecond!=nowSecond) { 163 | this.currentSecond = nowSecond; 164 | this.nbBytesReadThisSecond = 0; 165 | } 166 | 167 | return 1000-(now%1000); 168 | } 169 | 170 | 171 | /** 172 | * Increases the number of bytes read this second to the given number. 173 | * 174 | * @param nbRead number of bytes that have been read or skipped from the underlying stream. 175 | */ 176 | private void addToLimitCounter(long nbRead) { 177 | updateLimitCounter(); 178 | 179 | this.nbBytesReadThisSecond += nbRead; 180 | } 181 | 182 | 183 | //////////////////////////////// 184 | // InputStream implementation // 185 | //////////////////////////////// 186 | 187 | public int read() throws IOException { 188 | 189 | long bpsLimit = Configuration.getSpeedValue(); 190 | 191 | // Wait until at least 1 byte is available if a limit is set 192 | if(bpsLimit>=0) 193 | getNbAllowedBytes(); 194 | 195 | // Read the byte from the underlying stream 196 | int i = in.read(); 197 | 198 | // Increase read counter by 1 199 | if(i>0) 200 | addToLimitCounter(1); 201 | 202 | return i; 203 | } 204 | 205 | public int read(byte[] bytes) throws IOException { 206 | return this.read(bytes, 0, bytes.length); 207 | } 208 | 209 | public int read(byte[] bytes, int off, int len) throws IOException { 210 | int nbRead; 211 | 212 | long bpsLimit = Configuration.getSpeedValue(); 213 | 214 | // Wait until at least 1 byte is available if a limit is set and try to read as many bytes are available 215 | // without exceeding the throughput limit or the number specified 216 | if(bpsLimit>=0 && Configuration.limitSpeed) 217 | nbRead = in.read(bytes, off, Math.min(getNbAllowedBytes(),len)); 218 | else 219 | nbRead = in.read(bytes, off, len); 220 | 221 | // Increase read counter by the number of bytes that have actually been read by the underlying stream 222 | if(nbRead>0) 223 | addToLimitCounter(nbRead); 224 | 225 | return nbRead; 226 | } 227 | 228 | public long skip(long l) throws IOException { 229 | 230 | long bpsLimit = Configuration.getSpeedValue(); 231 | 232 | long nbSkipped = in.skip(bpsLimit>=0?Math.min(getNbAllowedBytes(),l):l); 233 | 234 | // Increase read counter by the number of bytes that have actually been skipped by the underlying stream 235 | if(nbSkipped>0) 236 | addToLimitCounter(nbSkipped); 237 | 238 | return nbSkipped; 239 | } 240 | 241 | public int available() throws IOException { 242 | return in.available(); 243 | } 244 | 245 | public void close() throws IOException { 246 | in.close(); 247 | } 248 | 249 | public synchronized void mark(int i) { 250 | in.mark(i); 251 | } 252 | 253 | public synchronized void reset() throws IOException { 254 | in.reset(); 255 | } 256 | 257 | public boolean markSupported() { 258 | return in.markSupported(); 259 | } 260 | } -------------------------------------------------------------------------------- /src/minicopier/TransferTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | TransferTask.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier; 21 | import java.io.*; 22 | 23 | 24 | public class TransferTask extends Thread{ 25 | 26 | private Copier copier; 27 | 28 | private File source; 29 | 30 | private File destination; 31 | 32 | private File destinationFolder; 33 | 34 | private Boolean append; 35 | 36 | private Boolean paused; 37 | 38 | private Boolean cancel; 39 | 40 | private long totalSize; 41 | 42 | private long currentSize; 43 | 44 | boolean completed; 45 | 46 | boolean putInQueue; 47 | 48 | 49 | 50 | public TransferTask(Copier c, FileToTransfer file, boolean _app){ 51 | this.copier = c; 52 | this.source=file.getSourceFile(); 53 | this.destination=file.getDestinationFile(); 54 | this.destinationFolder=file.getDestinationFolder(); 55 | this.append=_app; 56 | this.paused = false; 57 | this.cancel = false; 58 | this.totalSize = file.getSize(); 59 | this.currentSize = 0; 60 | this.completed = false; 61 | this.putInQueue = false; 62 | } 63 | 64 | 65 | public boolean getCompleted(){ 66 | return this.completed; 67 | } 68 | 69 | 70 | public void setPause() { 71 | this.paused = true; 72 | } 73 | 74 | public void unpause() { 75 | synchronized(this) { 76 | this.paused = false; 77 | this.notifyAll(); 78 | } 79 | } 80 | 81 | public void setCancelAndQueue(boolean _putInQueue){ 82 | this.cancel = true; 83 | this.putInQueue = _putInQueue; 84 | } 85 | 86 | public boolean getPutInQueue(){ 87 | return this.putInQueue; 88 | } 89 | 90 | public boolean getCancel() { 91 | return this.cancel; 92 | } 93 | 94 | public void run() { 95 | // Streams declarations 96 | ThroughputLimitInputStream sourceFile = null; 97 | java.io.FileOutputStream destinationFile = null; 98 | 99 | // Read by segment of 0.5Mo 100 | int bufferSize = 512*1024; 101 | 102 | this.copier.setFileTotalSize(this.totalSize); 103 | this.copier.setFileCurrentSize(0); 104 | 105 | try { 106 | //creation of directories (if needed) 107 | this.destinationFolder.mkdirs(); 108 | // Creation of file (nothing done if already present) 109 | this.destination.createNewFile(); 110 | 111 | // Opening streams 112 | sourceFile = new ThroughputLimitInputStream(new java.io.FileInputStream(source)); 113 | destinationFile = new java.io.FileOutputStream(destination,this.append); 114 | 115 | if (append) { 116 | // Skip already copied bytes 117 | long already_copied = destination.length(); 118 | long jump_source; 119 | jump_source = sourceFile.skip(already_copied); 120 | 121 | //Might be useless (?) 122 | //risk of skipping too much (javadoc) 123 | while (jump_source != already_copied) { 124 | sourceFile = new ThroughputLimitInputStream(new java.io.FileInputStream(source)); 125 | jump_source = sourceFile.skip(already_copied); 126 | } 127 | 128 | this.copier.increaseFileCurrentSize(jump_source); 129 | } 130 | 131 | // Read by segment of 0.5Mo 132 | byte buffer[]=new byte[bufferSize]; 133 | int nbReads; 134 | 135 | while( (nbReads = sourceFile.read(buffer)) != -1 ) { 136 | destinationFile.write(buffer, 0, nbReads); 137 | 138 | this.copier.increaseFileCurrentSize(nbReads); 139 | 140 | if (this.paused) { 141 | synchronized(this) { 142 | try{ 143 | this.copier.setPause(true); 144 | System.out.println("COPY PAUSED"); 145 | wait(); 146 | this.copier.setPause(false); 147 | System.out.println("COPY RESUMED"); 148 | } 149 | catch (InterruptedException e) {} 150 | } 151 | 152 | } 153 | 154 | if (this.cancel) { //Skip or cancel requested by user 155 | return; 156 | } 157 | 158 | } 159 | 160 | // Copy successful 161 | this.completed = true; 162 | //System.out.println("Transfer completed !"); 163 | 164 | } catch( java.io.FileNotFoundException f ) { 165 | 166 | } catch( java.io.IOException e ) { 167 | System.out.println("IO Exception !"); 168 | 169 | } finally { 170 | // Whatever happens, closing streams 171 | try { 172 | sourceFile.close(); 173 | } catch(Exception e) { 174 | System.out.println("Error closing source file !"); 175 | } 176 | try { 177 | destinationFile.close(); 178 | } catch(Exception e) { 179 | System.out.println("Error closing destination file !"); 180 | } 181 | } 182 | 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/minicopier/configuration.ini: -------------------------------------------------------------------------------- 1 | #MiniCopier startup configuration file 2 | 3 | #Language 4 | #default : "SystemLocale" 5 | #You can force with : "fr", "en", ... 6 | language=Systemlocale 7 | 8 | #Always on top 9 | alwaysontop=true 10 | 11 | #Look and Feel 12 | #You can try with : "pgs","native","metal" 13 | lnf=pgs 14 | 15 | #Collision default action 16 | #"ask","cancel","overwrite","overwrite_older","resume" 17 | collision=ask 18 | 19 | #Symbolic links 20 | #"follow","ignore" 21 | symlinks=follow 22 | -------------------------------------------------------------------------------- /src/minicopier/gui/Credits.java: -------------------------------------------------------------------------------- 1 | /* 2 | Credits.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.Component; 23 | import javax.swing.*; 24 | 25 | import java.awt.*; 26 | import java.awt.event.ActionEvent; 27 | import java.awt.event.ActionListener; 28 | 29 | import minicopier.i18n.Language; 30 | import minicopier.Copier; 31 | 32 | public class Credits extends JDialog { 33 | 34 | private JTextArea credits; 35 | 36 | private JTextArea license; 37 | 38 | private JButton ok; 39 | 40 | public Credits(JFrame owner){ 41 | super(owner,true); 42 | 43 | this.setTitle(Language.get("Credits.Title")); 44 | this.setSize(360, 300); 45 | this.setLocationRelativeTo(null); 46 | 47 | JPanel mainPanel = new JPanel(); 48 | mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); 49 | mainPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 50 | 51 | mainPanel.setBorder(BorderFactory.createEmptyBorder(7,7,7,7)); 52 | 53 | //Panel with logo and version number 54 | JPanel logoPanel = new JPanel(); 55 | logoPanel.setLayout(new BoxLayout(logoPanel, BoxLayout.Y_AXIS)); 56 | logoPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 57 | 58 | 59 | JLabel logo = new JLabel(""); 60 | logo.setIcon(new ImageIcon(MainFrame.frame.imageFromJar("img/minicopier-logo.png"))); 61 | 62 | JLabel version = new JLabel(Language.get("Credits.Version")+" : "+Copier.version); 63 | logoPanel.add(logo); 64 | logoPanel.add(version); 65 | logo.setAlignmentX(Component.CENTER_ALIGNMENT); 66 | version.setAlignmentX(Component.CENTER_ALIGNMENT); 67 | 68 | //Tabbed pane with credits and license 69 | JTabbedPane tabbedPane = new JTabbedPane(); 70 | 71 | //Credits Panel 72 | JPanel creditsPanel = new JPanel(); 73 | creditsPanel.setLayout(new BorderLayout()); 74 | 75 | this.credits = new JTextArea(); 76 | credits.setEditable(false); 77 | credits.setWrapStyleWord(true); 78 | credits.setLineWrap(true); 79 | credits.setText(getCreditsText()); 80 | credits.setCaretPosition(0); 81 | credits.setTabSize(1); 82 | 83 | JScrollPane jspCredits = new JScrollPane(credits); 84 | creditsPanel.add(jspCredits,BorderLayout.CENTER); 85 | 86 | //License Panel 87 | JPanel licensePanel = new JPanel(); 88 | licensePanel.setLayout(new BorderLayout()); 89 | 90 | this.license = new JTextArea(); 91 | license.setEditable(false); 92 | license.setWrapStyleWord(true); 93 | license.setLineWrap(true); 94 | license.setText(getLicenseText()); 95 | license.setCaretPosition(0); 96 | credits.setTabSize(1); 97 | 98 | JScrollPane jspLicense = new JScrollPane(license); 99 | licensePanel.add(jspLicense,BorderLayout.CENTER); 100 | 101 | 102 | tabbedPane.add(Language.get("Credits.Title"),creditsPanel); 103 | tabbedPane.add(Language.get("Credits.License.Title"),licensePanel); 104 | 105 | mainPanel.add(logoPanel); 106 | mainPanel.add(tabbedPane); 107 | 108 | this.ok = new JButton("OK"); 109 | this.ok.addActionListener(new ActionOK()); 110 | mainPanel.add(Box.createVerticalStrut(5)); 111 | mainPanel.add(ok); 112 | ok.setAlignmentX(Component.CENTER_ALIGNMENT); 113 | 114 | this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 115 | this.getContentPane().add(mainPanel); 116 | this.setVisible(true); 117 | } 118 | 119 | public String getCreditsText() { 120 | StringBuffer credits = new StringBuffer(); 121 | 122 | credits.append(Language.get("Credits.Credits.Homepage")+"\n"); 123 | credits.append("http://www.adriancourreges.com/projects/minicopier\n\n"); 124 | credits.append(Language.get("Credits.Credits.Development")+"\n"); 125 | credits.append(Language.get("Credits.Credits.Developers")+"\n\n"); 126 | credits.append(Language.get("Credits.Credits.LanguageTranslation")+"\n"); 127 | credits.append(Language.get("Credits.Credits.LanguageContributors")+"\n\n"); 128 | credits.append(Language.get("Credits.Credits.SendMail")+"\n"); 129 | credits.append("a.courreges@gmail.com"); 130 | 131 | return credits.toString(); 132 | } 133 | 134 | public String getLicenseText() { 135 | StringBuffer license = new StringBuffer(); 136 | 137 | license.append(Language.get("Credits.License.Intro")+"\n\n"); 138 | license.append("Copyright (C) Adrian Courreges\n\n"); 139 | license.append("This program is free software; you can redistribute it and/or modify " + 140 | "it under the terms of the GNU General Public License as published by " + 141 | "the Free Software Foundation; either version 2 of the License, or " + 142 | " (at your option) any later version.\n\n" + 143 | "This program is distributed in the hope that it will be useful, " + 144 | "but WITHOUT ANY WARRANTY; without even the implied warranty of " + 145 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " + 146 | "GNU General Public License for more details.\n\n" + 147 | "You should have received a copy of the GNU General Public License " + 148 | "along with this program; see the file COPYING. If not, write to the " + 149 | "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA."); 150 | 151 | return license.toString(); 152 | 153 | } 154 | 155 | public void exit(){ 156 | this.dispose(); 157 | } 158 | 159 | private class ActionOK implements ActionListener { 160 | public void actionPerformed(ActionEvent e) { 161 | exit(); 162 | } 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /src/minicopier/gui/DialogMsg.java: -------------------------------------------------------------------------------- 1 | /* 2 | DialogMsg.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | import javax.swing.JOptionPane; 22 | import minicopier.i18n.Language; 23 | 24 | public class DialogMsg { 25 | 26 | //byte 27 | private static String b; 28 | 29 | private static String kb; //kB 30 | 31 | private static String mb; //MB 32 | 33 | private static String gb; //GB 34 | 35 | private static String tb; //TB 36 | 37 | private static String bps, kbps, mbps, gbps, tbps; 38 | 39 | private static String day, hour, min, sec; 40 | 41 | public static void init() { 42 | b = Language.get("DialogMsg.byte"); 43 | kb = Language.get("DialogMsg.kilobyte"); 44 | mb = Language.get("DialogMsg.megabyte"); 45 | gb = Language.get("DialogMsg.gigabyte"); 46 | tb = Language.get("DialogMsg.terabyte"); 47 | bps = Language.get("DialogMsg.byteps"); 48 | kbps = Language.get("DialogMsg.kilobyteps"); 49 | mbps = Language.get("DialogMsg.megabyteps"); 50 | gbps = Language.get("DialogMsg.gigabyteps"); 51 | tbps = Language.get("DialogMsg.terabyteps"); 52 | day = "d"; 53 | hour = "h"; 54 | min = "m"; 55 | sec = "s"; 56 | } 57 | 58 | 59 | 60 | 61 | public static boolean displayBasketInstructions(boolean empty) { 62 | boolean clearBasket = false; 63 | if (empty) { //Basket is empty, we display use instructions 64 | JOptionPane.showMessageDialog(MainFrame.frame, 65 | Language.get("DialogMsg.displayBasketInstructions.EmptyText"), 66 | Language.get("DialogMsg.displayBasketInstructions.Title"), 67 | JOptionPane.INFORMATION_MESSAGE); 68 | } else { //Basket not empty, possibility to clear 69 | Object[] options = { 70 | Language.get("DialogMsg.displayBasketInstructions.ClearButton"), 71 | Language.get("DialogMsg.displayBasketInstructions.CancelButton")}; 72 | int n = JOptionPane.showOptionDialog(MainFrame.frame, 73 | Language.get("DialogMsg.displayBasketInstructions.FullText"), 74 | Language.get("DialogMsg.displayBasketInstructions.Title"), 75 | JOptionPane.YES_NO_OPTION, 76 | JOptionPane.QUESTION_MESSAGE, 77 | null, 78 | options, 79 | options[1]); 80 | clearBasket = (n==0); 81 | 82 | } 83 | return clearBasket; 84 | } 85 | 86 | 87 | public static int confirmSkip(){ 88 | Object[] options = {Language.get("DialogMsg.confirmSkip.QueueButton"), 89 | Language.get("DialogMsg.confirmSkip.NoButton"), 90 | Language.get("DialogMsg.confirmSkip.CancelButton")}; 91 | int n = JOptionPane.showOptionDialog(MainFrame.frame, 92 | Language.get("DialogMsg.confirmSkip.Text"), 93 | Language.get("DialogMsg.confirmSkip.Title"), 94 | JOptionPane.YES_NO_CANCEL_OPTION, 95 | JOptionPane.QUESTION_MESSAGE, 96 | null, 97 | options, 98 | options[2]); 99 | return n; 100 | } 101 | 102 | 103 | 104 | 105 | public static String askNewName(String oldName) { 106 | return JOptionPane.showInputDialog(MainFrame.frame, 107 | Language.get("DialogMsg.askNewName.Text"), 108 | oldName); 109 | } 110 | 111 | public static void renameError(){ 112 | JOptionPane.showMessageDialog(MainFrame.frame, 113 | Language.get("DialogMsg.renameError.Text"), 114 | Language.get("DialogMsg.renameError.Title"), 115 | JOptionPane.ERROR_MESSAGE); 116 | 117 | } 118 | 119 | public static void errorOverwrite() { 120 | JOptionPane.showMessageDialog(MainFrame.frame, 121 | Language.get("DialogMsg.errorOverwrite.Text"), 122 | Language.get("DialogMsg.errorOverwrite.Title"), 123 | JOptionPane.ERROR_MESSAGE); 124 | } 125 | 126 | public static int alreadyExistsChoice(String sourcePath, long sourceSize, 127 | String targetPath, long destSize){ 128 | Object[] options = {Language.get("DialogMsg.alreadyExistsChoice.OverwriteButton"), 129 | Language.get("DialogMsg.alreadyExistsChoice.ResumeButton"), 130 | Language.get("DialogMsg.alreadyExistsChoice.RenameButton"), 131 | Language.get("DialogMsg.alreadyExistsChoice.CancelButton")}; 132 | int n = JOptionPane.showOptionDialog(MainFrame.frame, 133 | Language.get("DialogMsg.alreadyExistsChoice.Text1") + 134 | Language.get("DialogMsg.alreadyExistsChoice.Source") + 135 | " : "+ prettySize(sourceSize)+ "\n"+ 136 | sourcePath + 137 | Language.get("DialogMsg.alreadyExistsChoice.Target")+ 138 | " : "+ prettySize(destSize)+ "\n" 139 | +targetPath+"\n\n" 140 | + Language.get("DialogMsg.alreadyExistsChoice.Text2"), 141 | Language.get("DialogMsg.alreadyExistsChoice.Title"), 142 | JOptionPane.YES_NO_CANCEL_OPTION, 143 | JOptionPane.QUESTION_MESSAGE, 144 | null, 145 | options, 146 | options[3]); 147 | return n; 148 | } 149 | 150 | 151 | public static boolean transferErrorChoice(){ 152 | Object[] options = {Language.get("DialogMsg.transferErrorChoice.QueueButton"), 153 | Language.get("DialogMsg.transferErrorChoice.AbortButton")}; 154 | int n = JOptionPane.showOptionDialog(MainFrame.frame, 155 | Language.get("DialogMsg.transferErrorChoice.Text"), 156 | Language.get("DialogMsg.transferErrorChoice.Title"), 157 | JOptionPane.YES_NO_OPTION, 158 | JOptionPane.ERROR_MESSAGE, 159 | null, 160 | options, 161 | options[0]); 162 | return (n==0); 163 | } 164 | 165 | public static void displayWelcome(){ 166 | JOptionPane.showMessageDialog(null, 167 | Language.get("DialogMsg.welcome.Text"), 168 | Language.get("DialogMsg.welcome.Title"), 169 | JOptionPane.INFORMATION_MESSAGE); 170 | } 171 | 172 | public static void displayCredits() { 173 | JOptionPane.showMessageDialog(MainFrame.frame, 174 | "MiniCopier - 0.2\nNovember 2007\nAdrian Courrèges\n\n" 175 | +"For bug reports or suggestions,\n" 176 | +"please, send an email to :\n" 177 | +"a.courreges@gmail.com", 178 | "Credits", 179 | JOptionPane.INFORMATION_MESSAGE); 180 | } 181 | 182 | /** Conversion of a long representing the size of a file 183 | * in bytes into a user-friendly String. 184 | * e.g. : 71430144 -> "68.12 MB" 185 | * @param s size in bytes 186 | */ 187 | public static String prettySize(long s){ 188 | String unit = ""; 189 | double cut; 190 | 191 | if (s < 1024) { 192 | return s + " " + b; 193 | } else if (s < Math.pow(1024,2)){ 194 | cut = ((double) s) / Math.pow(1024,1); 195 | unit = " " + kb; 196 | } else if (s < Math.pow(1024,3)) { 197 | cut = ((double) s) / Math.pow(1024,2); 198 | unit = " " + mb; 199 | } else if (s < Math.pow(1024,4)) { 200 | cut = ((double) s) / Math.pow(1024,3); 201 | unit = " " + gb; 202 | } else { 203 | cut = ((double) s) / Math.pow(1024,4); 204 | unit = " " + tb; 205 | } 206 | 207 | cut *= 100.0; 208 | cut = Math.floor(cut+0.5); 209 | cut /= 100.0; 210 | 211 | return cut + unit; 212 | } 213 | 214 | public static String prettySpeed(long s){ 215 | String unit = ""; 216 | double cut; 217 | 218 | if (s < 1024) { 219 | return s + " " + bps; 220 | } else if (s < Math.pow(1024,2)){ 221 | cut = ((double) s) / Math.pow(1024,1); 222 | unit = " " + kbps; 223 | } else if (s < Math.pow(1024,3)) { 224 | cut = ((double) s) / Math.pow(1024,2); 225 | unit = " " + mbps; 226 | } else if (s < Math.pow(1024,4)) { 227 | cut = ((double) s) / Math.pow(1024,3); 228 | unit = " " + gbps; 229 | } else { 230 | cut = ((double) s) / Math.pow(1024,4); 231 | unit = " " + tbps; 232 | } 233 | 234 | cut *= 100.0; 235 | cut = Math.floor(cut+0.5); 236 | cut /= 100.0; 237 | 238 | return cut + unit; 239 | } 240 | 241 | public static String prettyTime(long t){ 242 | StringBuffer sb = new StringBuffer(); 243 | if (t < 60) { // x sec 244 | sb.append(t).append(sec); 245 | return sb.toString(); 246 | } 247 | if (t < 3600) { // x min y sec 248 | sb.append(t/60).append(min).append(" "); 249 | t = t % 60; 250 | if (t > 0) { 251 | //if (t<10) sb.append("0"); 252 | sb.append(t).append(sec); 253 | } 254 | 255 | return sb.toString(); 256 | } 257 | if (t < 86400) {// x h y min 258 | sb.append(t/3600).append(hour).append(" "); 259 | t = t % 3600; 260 | if (t/60 > 0) { 261 | //if (t<10) sb.append("0"); 262 | sb.append(t/60).append(min); 263 | } 264 | 265 | return sb.toString(); 266 | } 267 | // x days y hours 268 | sb.append(t/86400).append(day).append(" "); 269 | t = t % 86400; 270 | if (t/3600 > 0) { 271 | sb.append(t/3600).append(hour); 272 | } 273 | 274 | return sb.toString(); 275 | } 276 | 277 | } 278 | -------------------------------------------------------------------------------- /src/minicopier/gui/FailedPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | FailedPanel.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.BorderLayout; 23 | import java.awt.Component; 24 | import java.awt.Dimension; 25 | 26 | import javax.swing.*; 27 | import javax.swing.table.DefaultTableCellRenderer; 28 | import javax.swing.table.DefaultTableModel; 29 | 30 | import minicopier.i18n.Language; 31 | 32 | public class FailedPanel extends JPanel { 33 | 34 | 35 | private MainFrame mainFrame; 36 | 37 | protected QueueJButton retry; 38 | 39 | protected QueueJButton removeFailed; 40 | 41 | protected DefaultTableModel failedModel; 42 | 43 | protected JTable failedList; 44 | 45 | public FailedPanel(MainFrame f){ 46 | super(); 47 | 48 | this.mainFrame = f; 49 | 50 | this.retry = new QueueJButton("img/retry.gif"); 51 | this.retry.setToolTipText(Language.get("Tooltip.Failed.Retry")); 52 | 53 | 54 | this.removeFailed = new QueueJButton("img/delete.gif"); 55 | this.removeFailed.setToolTipText(Language.get("Tooltip.Failed.Clear")); 56 | 57 | failedModel = mainFrame.copier.failedItems.getTableModel(); 58 | failedList = new JTable(failedModel); 59 | //transferList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 60 | failedList.getColumnModel().getColumn(1).setCellRenderer(new RightTableCellRenderer()); 61 | failedList.getColumnModel().getColumn(1).setMaxWidth(80); 62 | failedList.getColumnModel().getColumn(1).setMinWidth(80); 63 | 64 | 65 | 66 | this.setLayout(new BorderLayout()); 67 | 68 | 69 | JScrollPane jspFailed = new JScrollPane(failedList); 70 | jspFailed.setViewportView(failedList); 71 | jspFailed.setPreferredSize(new Dimension(40,40)); 72 | //transferList.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); 73 | //jspTransfer.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 74 | 75 | 76 | //Subpanel (west) with queue management buttons 77 | JPanel queueButtonsPanel = new JPanel(); 78 | queueButtonsPanel.setLayout(new BoxLayout(queueButtonsPanel, BoxLayout.Y_AXIS)); 79 | queueButtonsPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 80 | queueButtonsPanel.add(this.retry,Component.CENTER_ALIGNMENT); 81 | queueButtonsPanel.add(this.removeFailed); 82 | 83 | 84 | this.add(queueButtonsPanel,BorderLayout.WEST); 85 | this.add(jspFailed,BorderLayout.CENTER); 86 | 87 | 88 | } 89 | 90 | private class RightTableCellRenderer extends DefaultTableCellRenderer { 91 | public RightTableCellRenderer() { 92 | setHorizontalAlignment(RIGHT); 93 | setVerticalAlignment(CENTER); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/minicopier/gui/MainFrame.java: -------------------------------------------------------------------------------- 1 | /* 2 | MainFrame.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import minicopier.i18n.Language; 23 | 24 | import java.awt.*; 25 | import java.awt.event.*; 26 | import java.awt.dnd.*; 27 | import java.awt.datatransfer.*; 28 | import java.io.*; 29 | import java.util.*; 30 | import java.util.List; 31 | 32 | import javax.swing.*; 33 | import javax.swing.event.ChangeEvent; 34 | import javax.swing.event.ChangeListener; 35 | 36 | import minicopier.Configuration; 37 | import minicopier.Copier; 38 | 39 | 40 | public class MainFrame extends JFrame{ 41 | 42 | public static MainFrame frame; 43 | 44 | protected Copier copier; 45 | 46 | private SupPanel supPanel; 47 | 48 | private TransfersPanel transfersPanel; 49 | 50 | private FailedPanel failedPanel; 51 | 52 | private OptionsPanel optionsPanel; 53 | 54 | 55 | public MainFrame(Copier cop) { 56 | 57 | super(); 58 | 59 | frame = this; 60 | 61 | DialogMsg.init(); 62 | 63 | //Look And Feel 64 | 65 | if (Configuration.lookAndFeel.equals("pgs")){ 66 | try { 67 | UIManager.setLookAndFeel("com.pagosoft.plaf.PgsLookAndFeel"); 68 | } catch(Exception e) {} 69 | } 70 | 71 | //Classic swing 72 | else { 73 | UIManager.put("swing.boldMetal", Boolean.FALSE); 74 | if (Configuration.lookAndFeel.equals("native")) { 75 | try { 76 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 77 | //SwingUtilities.updateComponentTreeUI(this); 78 | } catch (Exception e) {} 79 | } 80 | } 81 | this.copier = cop; 82 | copier.setGui(this); 83 | 84 | this.setTitle(copier.name); 85 | this.setSize(470, 400); 86 | //this.setAlwaysOnTop(Configuration.alwaysOnTop); 87 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 88 | this.setLocationRelativeTo(null); 89 | this.setIconImage(imageFromJar("img/icon.jpg")); 90 | //this.setUndecorated(true); 91 | 92 | this.supPanel = new SupPanel(this); 93 | 94 | this.transfersPanel = new TransfersPanel(this); 95 | 96 | this.failedPanel = new FailedPanel(this); 97 | 98 | this.optionsPanel = new OptionsPanel(this); 99 | 100 | 101 | 102 | //mainPanel includes a JPanel (top) and a JTabbedPane 103 | JPanel mainPanel = new JPanel(); 104 | mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); 105 | mainPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 106 | 107 | 108 | mainPanel.add(this.supPanel); 109 | 110 | // Linking the Panel to the controllers 111 | RequestPauseResume actList = new RequestPauseResume(); 112 | ActionSkip skipList = new ActionSkip(); 113 | ActionCancel cancelList = new ActionCancel(); 114 | ActionCredits creditsList = new ActionCredits(); 115 | ActionBasket basketList = new ActionBasket(); 116 | 117 | supPanel.basket.addMouseListener(basketList); 118 | supPanel.pause.addActionListener(actList); 119 | supPanel.skip.addActionListener(skipList); 120 | supPanel.cancel.addActionListener(cancelList); 121 | 122 | DropTargetListener dropL = new Drop2Basket(); 123 | DropTargetListener dropFL = new Drop2Folder(); 124 | DropTarget dropT = new DropTarget(this.supPanel.basket, dropL); 125 | DropTarget dropFT = new DropTarget(this.supPanel.paste, dropFL); 126 | 127 | 128 | 129 | 130 | JTabbedPane tabbedPane = new JTabbedPane(); 131 | 132 | //Adding the transfers list to the first tab 133 | tabbedPane.addTab(Language.get("MainFrame.TransfersPane.title"), new ImageIcon(imageFromJar("img/list.png")) ,transfersPanel); 134 | //Linking the Panel to the controllers 135 | ActionQueueButtons queueButtonsListener = new ActionQueueButtons(); 136 | transfersPanel.putFirst.addActionListener(queueButtonsListener); 137 | transfersPanel.putUp.addActionListener(queueButtonsListener); 138 | transfersPanel.putDown.addActionListener(queueButtonsListener); 139 | transfersPanel.putLast.addActionListener(queueButtonsListener); 140 | transfersPanel.delete.addActionListener(queueButtonsListener); 141 | 142 | tabbedPane.addTab(Language.get("MainFrame.FailedPane.title"), new ImageIcon(imageFromJar("img/failed.gif")) ,failedPanel); 143 | //Linking the Panel to the controllers 144 | ActionFailedButtons failedButtonsListener = new ActionFailedButtons(); 145 | failedPanel.retry.addActionListener(failedButtonsListener); 146 | failedPanel.removeFailed.addActionListener(failedButtonsListener); 147 | 148 | //Adding the options panel to the second tab 149 | tabbedPane.addTab(Language.get("MainFrame.OptionsPane.title"),new ImageIcon(imageFromJar("img/options.png")),optionsPanel); 150 | //Linking the Panel to the controllers 151 | ActionCollision collisionList = new ActionCollision(); 152 | ActionSymbolic symbolicList = new ActionSymbolic(); 153 | 154 | optionsPanel.collisionBox.addActionListener(collisionList); 155 | optionsPanel.symbolicBox.addActionListener(symbolicList); 156 | optionsPanel.credits.addActionListener(creditsList); 157 | optionsPanel.speedLimitBox.addActionListener(new ActionLimitSpeed()); 158 | ActionSpeedChange speedLimitChange = new ActionSpeedChange(); 159 | optionsPanel.speedValue.addChangeListener(speedLimitChange); 160 | optionsPanel.speedUnitBox.addActionListener(speedLimitChange); 161 | 162 | mainPanel.add(tabbedPane); 163 | 164 | 165 | this.getContentPane().add(mainPanel); 166 | this.setVisible(true); 167 | 168 | 169 | RefreshStats refresh = new RefreshStats(500); 170 | refresh.start(); 171 | 172 | } 173 | 174 | public Image imageFromJar(String path){ 175 | return Toolkit.getDefaultToolkit() 176 | .getImage(getClass().getClassLoader().getResource(path)); 177 | } 178 | 179 | 180 | private class RequestPauseResume implements ActionListener { 181 | public void actionPerformed(ActionEvent e) 182 | { 183 | // to synchro (?) 184 | if(copier.getPause()) { //currently paused 185 | copier.unpause(); 186 | } else { //currently copying 187 | copier.pause(); 188 | } 189 | } 190 | } 191 | 192 | 193 | private class Drop2Basket implements DropTargetListener { 194 | public void drop(DropTargetDropEvent dtde) { 195 | 196 | 197 | dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 198 | 199 | try { 200 | 201 | Transferable tr = dtde.getTransferable(); 202 | DataFlavor[] flavors = tr.getTransferDataFlavors(); 203 | 204 | for (int i = 0; i < flavors.length; i++) { 205 | 206 | DataFlavor fl = flavors[i]; 207 | 208 | Object obj = tr.getTransferData(flavors[i]); 209 | 210 | 211 | //For Windows and Mac 212 | if (DataFlavor.javaFileListFlavor.equals(fl)) { 213 | List files = (List)tr.getTransferData(fl); 214 | 215 | for (File fi : files){ 216 | System.out.println(fi.toURI().toString()); 217 | copier.addURIString2basket(fi.toURI().toString()); 218 | } 219 | 220 | dtde.dropComplete(true); 221 | basketSizeSignal(); 222 | return; 223 | } 224 | 225 | //For Linux and Mac 226 | else if (obj instanceof String && "uri-list".equals(flavors[i].getSubType()) ){ 227 | 228 | String allFilesPath; 229 | allFilesPath = (String)obj; 230 | 231 | Scanner scan = new Scanner(allFilesPath.trim()); 232 | 233 | while (scan.hasNextLine()) { 234 | copier.addURIString2basket(scan.nextLine()); 235 | } 236 | 237 | dtde.dropComplete(true); 238 | basketSizeSignal(); 239 | return; 240 | 241 | } 242 | 243 | } 244 | 245 | } catch (Exception e) { 246 | e.printStackTrace(); 247 | dtde.rejectDrop(); 248 | } 249 | 250 | dtde.rejectDrop(); 251 | 252 | } 253 | 254 | public void dragExit(DropTargetEvent e){} 255 | public void dropActionChanged(DropTargetDragEvent e){} 256 | public void dragOver(DropTargetDragEvent e){} 257 | public void dragEnter(DropTargetDragEvent e){} 258 | 259 | 260 | } 261 | 262 | private class Drop2Folder implements DropTargetListener { 263 | public void drop(DropTargetDropEvent dtde) { 264 | 265 | dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 266 | 267 | try { 268 | 269 | Transferable tr = dtde.getTransferable(); 270 | DataFlavor[] flavors = tr.getTransferDataFlavors(); 271 | 272 | for (int i = 0; i < flavors.length; i++) { 273 | 274 | DataFlavor fl = flavors[i]; 275 | 276 | Object obj = tr.getTransferData(flavors[i]); 277 | 278 | //For Windows and Mac 279 | if (DataFlavor.javaFileListFlavor.equals(fl)) { 280 | List files = (List)tr.getTransferData(fl); 281 | 282 | Iterator ite = files.iterator(); 283 | 284 | if (files.size() == 1) { 285 | copier.paste2URIString(ite.next().toURI().toString()); 286 | } 287 | 288 | dtde.dropComplete(true); 289 | basketSizeSignal(); 290 | 291 | return; 292 | 293 | } 294 | 295 | //For Linux and Mac 296 | else if (obj instanceof String && "uri-list".equals(flavors[i].getSubType()) ){ 297 | 298 | String allFilesPath; 299 | allFilesPath = (String)obj; 300 | 301 | Scanner scan = new Scanner(allFilesPath.trim()); 302 | 303 | String destinationFolderURIString = scan.nextLine(); 304 | 305 | if (!scan.hasNextLine()) { 306 | copier.paste2URIString(destinationFolderURIString); 307 | } 308 | 309 | dtde.dropComplete(true); 310 | basketSizeSignal(); 311 | 312 | return; 313 | 314 | } 315 | 316 | } 317 | 318 | } catch (Exception e) { 319 | e.printStackTrace(); 320 | dtde.rejectDrop(); 321 | } 322 | 323 | dtde.rejectDrop(); 324 | 325 | } 326 | 327 | public void dragExit(DropTargetEvent e){} 328 | public void dropActionChanged(DropTargetDragEvent e){} 329 | public void dragOver(DropTargetDragEvent e){} 330 | public void dragEnter(DropTargetDragEvent e){} 331 | 332 | } 333 | 334 | public void changeCurrentFileSignal() { 335 | supPanel.currentFileSource.setText(this.copier.getCurrentFileSource()); 336 | supPanel.currentFileDestination.setText(this.copier.getCurrentFileDestination()); 337 | } 338 | 339 | public void changePauseStateSignal(boolean b) { 340 | if (b) { //Copier has been paused 341 | setTitle(Language.get("MainFrame.paused")+" " + getTitle()); 342 | supPanel.pause.setText(Language.get("MainFrame.SupPanel.ResumeButton")); 343 | } else { //Copier has been resumed 344 | //setTitle(Copier.name); 345 | supPanel.pause.setText(Language.get("MainFrame.SupPanel.PauseButton")); 346 | } 347 | } 348 | 349 | public void totalSizeSignal() { 350 | String totalSize = DialogMsg.prettySize(copier.getQueueTotalSize()); 351 | supPanel.barTotalSize.setText(totalSize); 352 | } 353 | 354 | public void currentSizeSignal() { 355 | String currentSize = DialogMsg.prettySize(copier.getFileTotalSize()); 356 | supPanel.barCurrentSize.setText(currentSize); 357 | } 358 | 359 | public void basketSizeSignal() { 360 | supPanel.basketContent.setText(Language.get("MainFrame.SupPanel.BasketContent")+" "+copier.basketLength()); 361 | } 362 | 363 | 364 | 365 | 366 | private class RefreshStats extends Thread { 367 | 368 | //Delay between two displays (ms) 369 | private int refreshRate; 370 | 371 | public RefreshStats(int l){ 372 | this.refreshRate = l; 373 | } 374 | 375 | public void setRefreshRate(int l){ 376 | this.refreshRate = l; 377 | } 378 | 379 | public void run() { 380 | Vector historyBytes = new Vector(); 381 | int maxSize = 20; 382 | 383 | while (true) { 384 | long timeInit = System.currentTimeMillis(); 385 | if (!copier.getPause()){ 386 | historyBytes.add(0,copier.readAndInitBytesCounter()); 387 | if (historyBytes.size() > maxSize) historyBytes.removeElementAt(historyBytes.size()-1); 388 | double average = 0; 389 | for (long l : historyBytes){ 390 | average += l; 391 | } 392 | try{ 393 | average /= (historyBytes.size()*refreshRate/1000f); 394 | //System.out.println(DialogMsg.prettySize((long)average)); 395 | 396 | String totalETA = "%"; 397 | String currentETA = "%"; 398 | String currentSpeed = ""; 399 | if (average > 0){ 400 | if (copier.getTotalBytesRemaining()>0) { 401 | totalETA += " - "+DialogMsg.prettyTime((long)(copier.getTotalBytesRemaining()/average)); 402 | currentSpeed = " ("+DialogMsg.prettySpeed((long)average)+")"; 403 | } 404 | if (copier.getCurrentBytesRemaining()>0) 405 | currentETA += " - "+DialogMsg.prettyTime((long)(copier.getCurrentBytesRemaining()/average)); 406 | } 407 | supPanel.mainBar.setValue(copier.getTotalPercent()); 408 | supPanel.fileBar.setValue(copier.getCurrentPercent()); 409 | supPanel.mainBar.setString(copier.getTotalPercent()+totalETA); 410 | supPanel.fileBar.setString(copier.getCurrentPercent()+currentETA); 411 | setTitle(copier.getTotalPercent()+"%"+currentSpeed+" MiniCopier"); 412 | } catch (Exception e){e.printStackTrace();} 413 | } 414 | try {Thread.sleep(refreshRate-(int)(System.currentTimeMillis()-timeInit));} 415 | catch (Exception e){} 416 | 417 | } 418 | } 419 | } 420 | 421 | private class ActionQueueButtons implements ActionListener { 422 | public void actionPerformed(ActionEvent e) 423 | { 424 | synchronized (Copier.mainQueue) { 425 | int[] i = transfersPanel.transferList.getSelectedRows(); 426 | int[] newSelectedIndexes = {-1,-1}; 427 | 428 | 429 | if (i.length == 0) { return; } //something must be selected 430 | 431 | else if (e.getSource() == transfersPanel.putFirst){ 432 | newSelectedIndexes = Copier.mainQueue.putFirst(i); 433 | 434 | } 435 | else if (e.getSource() == transfersPanel.putUp){ 436 | newSelectedIndexes = Copier.mainQueue.putUp(i); 437 | } 438 | else if (e.getSource() == transfersPanel.putDown){ 439 | newSelectedIndexes = Copier.mainQueue.putDown(i); 440 | } 441 | else if (e.getSource() == transfersPanel.putLast){ 442 | newSelectedIndexes = Copier.mainQueue.putLast(i); 443 | } 444 | else if (e.getSource() == transfersPanel.delete){ 445 | newSelectedIndexes = Copier.mainQueue.remove(i); 446 | } 447 | else {} 448 | 449 | transfersPanel.transferList.clearSelection(); 450 | 451 | if (newSelectedIndexes[1] != -1) { 452 | transfersPanel.transferList.getSelectionModel(). 453 | addSelectionInterval(newSelectedIndexes[0], 454 | newSelectedIndexes[1]); 455 | } 456 | } 457 | } 458 | } 459 | 460 | private class ActionFailedButtons implements ActionListener { 461 | public void actionPerformed(ActionEvent e) 462 | { 463 | synchronized (Copier.failedItems) { 464 | int[] i = failedPanel.failedList.getSelectedRows(); 465 | 466 | if (i.length == 0) { return; } //something must be selected 467 | 468 | else if (e.getSource() == failedPanel.retry){ 469 | Copier.failedItems.retry(i); 470 | } 471 | else if (e.getSource() == failedPanel.removeFailed){ 472 | Copier.failedItems.remove(i); 473 | } 474 | 475 | transfersPanel.transferList.clearSelection(); 476 | } 477 | } 478 | } 479 | 480 | 481 | private class ActionSkip implements ActionListener { 482 | public void actionPerformed(ActionEvent e) 483 | { 484 | if (copier.getBusy()) { 485 | copier.pause(); 486 | int choice = DialogMsg.confirmSkip(); 487 | 488 | switch (choice) { 489 | //Skip with put in queue 490 | case 0: copier.skip(true); 491 | break; 492 | //Skip without put in queue 493 | case 1: copier.skip(false); 494 | break; 495 | //Cancel skip 496 | case 2 : break; 497 | } 498 | 499 | copier.unpause(); 500 | 501 | } 502 | 503 | } 504 | 505 | } 506 | 507 | private class ActionCancel implements ActionListener { 508 | public void actionPerformed(ActionEvent e){ 509 | //violent termination of the application 510 | // TODO : remove the part already copied of the 511 | // transfer (?) 512 | System.exit(0); 513 | } 514 | } 515 | 516 | private class ActionCredits implements ActionListener { 517 | public void actionPerformed(ActionEvent e){ 518 | //DialogMsg.displayCredits(); 519 | new Credits(MainFrame.frame); 520 | } 521 | } 522 | 523 | private class ActionBasket implements MouseListener { 524 | public void mousePressed(MouseEvent e){ 525 | //User clicked on the basket icon 526 | boolean want2Clear = DialogMsg.displayBasketInstructions(copier.basketLength()==0); 527 | if (want2Clear) { 528 | copier.clearBasket(); 529 | basketSizeSignal(); 530 | } 531 | 532 | } 533 | public void mouseReleased(MouseEvent e){} 534 | public void mouseExited(MouseEvent e){} 535 | public void mouseEntered(MouseEvent e){} 536 | public void mouseClicked(MouseEvent e){} 537 | } 538 | 539 | private class ActionCollision implements ActionListener { 540 | public void actionPerformed(ActionEvent e) { 541 | int i = optionsPanel.collisionBox.getSelectedIndex(); 542 | Configuration.collisionAction = i; 543 | } 544 | } 545 | 546 | private class ActionLimitSpeed implements ActionListener { 547 | public void actionPerformed(ActionEvent e) { 548 | boolean limitEnabled = optionsPanel.speedLimitBox.isSelected(); 549 | optionsPanel.speedValue.setEnabled(limitEnabled); 550 | optionsPanel.speedUnitBox.setEnabled(limitEnabled); 551 | Configuration.limitSpeed = limitEnabled; 552 | updateSpeed(); 553 | } 554 | } 555 | 556 | private class ActionSpeedChange implements ChangeListener, ActionListener { 557 | public void stateChanged(ChangeEvent e) { 558 | updateSpeed(); 559 | } 560 | 561 | public void actionPerformed(ActionEvent e) { 562 | updateSpeed(); 563 | } 564 | } 565 | 566 | private void updateSpeed(){ 567 | Configuration.setSpeedValue((int)Math.pow(1024, optionsPanel.speedUnitBox.getSelectedIndex())*(Integer)optionsPanel.speedValue.getValue()); 568 | //System.out.println(Configuration.nbBytesPerS); 569 | } 570 | 571 | private class ActionSymbolic implements ActionListener { 572 | public void actionPerformed(ActionEvent e) { 573 | int i = optionsPanel.symbolicBox.getSelectedIndex(); 574 | Configuration.symbolicLinkAction = i; 575 | } 576 | } 577 | 578 | 579 | 580 | } 581 | -------------------------------------------------------------------------------- /src/minicopier/gui/OptionsPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | OptionsPanel.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.Dimension; 23 | 24 | import javax.swing.*; 25 | 26 | import minicopier.Configuration; 27 | import minicopier.i18n.Language; 28 | 29 | public class OptionsPanel extends JPanel { 30 | 31 | private MainFrame mainFrame; 32 | 33 | protected JComboBox collisionBox; 34 | 35 | protected JComboBox symbolicBox; 36 | 37 | protected JCheckBox speedLimitBox; 38 | 39 | protected JSpinner speedValue; 40 | 41 | protected JComboBox speedUnitBox; 42 | 43 | protected JButton credits; 44 | 45 | public OptionsPanel(MainFrame f) { 46 | super(); 47 | 48 | this.mainFrame = f; 49 | 50 | this.credits = new JButton(Language 51 | .get("MainFrame.OptionsPane.creditsButton")); 52 | 53 | String[] collisionStrings = { 54 | Language.get("MainFrame.OptionsPane.collision.Ask"), 55 | Language.get("MainFrame.OptionsPane.collision.Cancel"), 56 | Language.get("MainFrame.OptionsPane.collision.Overwrite"), 57 | Language.get("MainFrame.OptionsPane.collision.OverwriteOld"), 58 | Language.get("MainFrame.OptionsPane.collision.Resume") }; 59 | collisionBox = new JComboBox(collisionStrings); 60 | // DefaultListCellRenderer rightRenderer = new 61 | // DefaultListCellRenderer(); 62 | // rightRenderer.setHorizontalAlignment(DefaultListCellRenderer.RIGHT); 63 | // collisionBox.setRenderer(rightRenderer); 64 | collisionBox.setSelectedIndex(Configuration.collisionAction); 65 | 66 | this.speedLimitBox = new JCheckBox(Language.get("MainFrame.OptionsPane.throughput.Sentence")); 67 | this.speedLimitBox.setSelected(false); 68 | SpinnerModel speedModel = new SpinnerNumberModel(1,1,9999,1); 69 | this.speedValue = new JSpinner(speedModel); 70 | this.speedValue.setEnabled(false); 71 | String[] unitValues = { 72 | Language.get("DialogMsg.byteps"), 73 | Language.get("DialogMsg.kilobyteps"), 74 | Language.get("DialogMsg.megabyteps"), 75 | Language.get("DialogMsg.gigabyteps")}; 76 | speedUnitBox = new JComboBox(unitValues); 77 | speedUnitBox.setSelectedIndex(2); 78 | speedUnitBox.setEnabled(false); 79 | 80 | String[] symbolicStrings = { 81 | Language.get("MainFrame.OptionsPane.symLinks.Follow"), 82 | Language.get("MainFrame.OptionsPane.symLinks.Ignore") }; 83 | symbolicBox = new JComboBox(symbolicStrings); 84 | 85 | symbolicBox.setSelectedIndex(Configuration.symbolicLinkAction); 86 | 87 | this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 88 | 89 | // Collision option 90 | JPanel collisionPanel = new JPanel(); 91 | collisionPanel.setLayout(new BoxLayout(collisionPanel, BoxLayout.X_AXIS)); 92 | collisionPanel.add(new JLabel(Language.get("MainFrame.OptionsPane.collision.Sentence"))); 93 | 94 | collisionPanel.add(Box.createHorizontalGlue()); 95 | collisionBox.setMaximumSize(collisionBox.getPreferredSize()); 96 | collisionPanel.add(collisionBox); 97 | collisionPanel.setBorder(BorderFactory.createTitledBorder(Language.get("MainFrame.OptionsPane.collision.Title"))); 98 | 99 | // Speed option 100 | JPanel speedPanel = new JPanel(); 101 | speedPanel.setLayout(new BoxLayout(speedPanel, BoxLayout.X_AXIS)); 102 | 103 | 104 | speedPanel.add(this.speedLimitBox); 105 | speedLimitBox.setMaximumSize(speedLimitBox.getPreferredSize()); 106 | speedPanel.add(Box.createHorizontalGlue()); 107 | speedPanel.add(this.speedValue); 108 | speedValue.setMaximumSize(new Dimension( 109 | speedValue.getMinimumSize().width, 110 | speedUnitBox.getMinimumSize().height) 111 | ); 112 | speedPanel.add(Box.createRigidArea(new Dimension(5,5))); 113 | speedPanel.add(speedUnitBox); 114 | speedUnitBox.setMaximumSize(speedUnitBox.getMinimumSize()); 115 | speedPanel.setBorder(BorderFactory.createTitledBorder(Language.get("MainFrame.OptionsPane.throughput.Title"))); 116 | 117 | 118 | 119 | 120 | // Symbolic link option 121 | JPanel symbolicPanel = new JPanel(); 122 | symbolicPanel.setLayout(new BoxLayout(symbolicPanel, BoxLayout.X_AXIS)); 123 | symbolicPanel.add(new JLabel(Language 124 | .get("MainFrame.OptionsPane.symLinks.Sentence"))); 125 | symbolicPanel.add(Box.createHorizontalGlue()); 126 | 127 | symbolicBox.setMaximumSize(symbolicBox.getPreferredSize()); 128 | // symbolicBox.setMinimumSize(collisionBox.getPreferredSize()); 129 | 130 | symbolicPanel.add(symbolicBox); 131 | symbolicPanel.setBorder(BorderFactory.createTitledBorder(Language 132 | .get("MainFrame.OptionsPane.symLinks.Title"))); 133 | 134 | JPanel optionsBottom = new JPanel(); 135 | optionsBottom.setLayout(new BoxLayout(optionsBottom, BoxLayout.X_AXIS)); 136 | optionsBottom.add(this.credits); 137 | optionsBottom.add(Box.createHorizontalGlue()); 138 | 139 | this.add(collisionPanel); 140 | this.add(speedPanel); 141 | this.add(symbolicPanel); 142 | this.add(Box.createVerticalGlue()); 143 | this.add(optionsBottom); 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/minicopier/gui/QueueJButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | QueueJButton.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.Dimension; 23 | 24 | import javax.swing.ImageIcon; 25 | import javax.swing.JButton; 26 | 27 | public class QueueJButton extends JButton{ 28 | 29 | public QueueJButton(String imagePath) { 30 | super(); 31 | this.setIcon(new ImageIcon(MainFrame.frame.imageFromJar(imagePath))); 32 | this.setMaximumSize(new Dimension(28,28)); 33 | this.setPreferredSize(new Dimension(28,28)); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/minicopier/gui/SupPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | SupPanel.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.Component; 23 | 24 | import javax.swing.*; 25 | 26 | import minicopier.i18n.Language; 27 | 28 | 29 | //Panel with DnD pictures + transfer stats 30 | public class SupPanel extends JPanel { 31 | 32 | private MainFrame mainFrame; 33 | 34 | protected JButton pause; 35 | 36 | protected JButton skip; 37 | 38 | protected JButton cancel; 39 | 40 | protected JLabel basket; 41 | 42 | protected JLabel basketContent; 43 | 44 | protected JLabel paste; 45 | 46 | protected JLabel barTotalSize; 47 | 48 | protected JLabel barCurrentSize; 49 | 50 | protected JLabel currentFileSource; 51 | 52 | protected JLabel currentFileDestination; 53 | 54 | protected JProgressBar mainBar; 55 | 56 | protected JProgressBar fileBar; 57 | 58 | public SupPanel(MainFrame f) { 59 | 60 | super(); 61 | 62 | this.mainFrame = f; 63 | 64 | this.pause = new JButton(Language.get("MainFrame.SupPanel.PauseButton")); 65 | this.skip = new JButton(Language.get("MainFrame.SupPanel.SkipButton")); 66 | this.cancel = new JButton(Language.get("MainFrame.SupPanel.CancelButton")); 67 | this.basket = new JLabel(""); 68 | this.basket.setIcon(new ImageIcon(mainFrame.imageFromJar("img/basket.png"))); 69 | this.basketContent = new JLabel(Language.get("MainFrame.SupPanel.BasketContent")+" 0"); 70 | this.paste = new JLabel(""); 71 | this.paste.setIcon(new ImageIcon(mainFrame.imageFromJar("img/paste.png"))); 72 | this.barTotalSize = new JLabel(""); 73 | this.barCurrentSize = new JLabel(""); 74 | this.currentFileSource = new JLabel(mainFrame.copier.getCurrentFileSource()); 75 | this.currentFileDestination = new JLabel(mainFrame.copier.getCurrentFileDestination()); 76 | 77 | //Tooltips 78 | this.basket.setToolTipText(Language.get("Tooltip.Basket")); 79 | this.paste.setToolTipText(Language.get("Tooltip.Paste")); 80 | 81 | this.mainBar = new JProgressBar(0, 100); 82 | mainBar.setValue(0); 83 | mainBar.setStringPainted(true); 84 | 85 | this.fileBar = new JProgressBar(0, 100); 86 | fileBar.setValue(0); 87 | fileBar.setStringPainted(true); 88 | 89 | 90 | this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 91 | this.setAlignmentX(Component.CENTER_ALIGNMENT); 92 | 93 | JPanel firstPanel = new JPanel(); 94 | 95 | firstPanel.setLayout(new BoxLayout(firstPanel, BoxLayout.X_AXIS)); 96 | firstPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 97 | 98 | Box basketPanel = Box.createVerticalBox(); 99 | 100 | //basketPanel.setLayout(new BoxLayout(basketPanel,BoxLayout.Y_AXIS)); 101 | basketPanel.add(basket); 102 | basketPanel.add(basketContent,Component.RIGHT_ALIGNMENT); 103 | 104 | basketPanel.setAlignmentX(Component.RIGHT_ALIGNMENT); 105 | 106 | firstPanel.add(basketPanel,Component.RIGHT_ALIGNMENT); 107 | 108 | //Sub JPanel with stats 109 | JPanel subJPanel1 = new JPanel(); 110 | subJPanel1.setLayout(new BoxLayout(subJPanel1, BoxLayout.Y_AXIS)); 111 | 112 | //Above Total progress bar 113 | JPanel aboveTotalBar = new JPanel(); 114 | aboveTotalBar.setLayout(new BoxLayout(aboveTotalBar,BoxLayout.X_AXIS)); 115 | aboveTotalBar.add(new JLabel(Language.get("MainFrame.SupPanel.TotalBarTitle"))); 116 | aboveTotalBar.add(Box.createHorizontalGlue()); 117 | aboveTotalBar.add(this.barTotalSize); 118 | 119 | subJPanel1.add(aboveTotalBar); 120 | subJPanel1.add(mainBar); 121 | 122 | //Above Current progress bar 123 | JPanel aboveCurrentBar = new JPanel(); 124 | aboveCurrentBar.setLayout(new BoxLayout(aboveCurrentBar,BoxLayout.X_AXIS)); 125 | aboveCurrentBar.add(new JLabel(Language.get("MainFrame.SupPanel.CurrentFileBarTitle"))); 126 | aboveCurrentBar.add(Box.createHorizontalGlue()); 127 | aboveCurrentBar.add(this.barCurrentSize); 128 | 129 | 130 | subJPanel1.add(aboveCurrentBar); 131 | subJPanel1.add(fileBar); 132 | 133 | firstPanel.add(subJPanel1); 134 | firstPanel.add(paste); 135 | this.add(firstPanel); 136 | 137 | //Panel with control buttons 138 | JPanel secondPanel = new JPanel(); 139 | secondPanel.setLayout(new BoxLayout(secondPanel, BoxLayout.X_AXIS)); 140 | //secondPanel.setAlignmentX(Component.RIGHT_ALIGNMENT); 141 | 142 | secondPanel.add(pause); 143 | secondPanel.add(skip); 144 | secondPanel.add(cancel); 145 | 146 | this.add(secondPanel); 147 | 148 | //Panel of files strings 149 | JPanel stringPanel = new JPanel(); 150 | stringPanel.setLayout(new BoxLayout(stringPanel, BoxLayout.X_AXIS)); 151 | 152 | 153 | //Subpanel "From:" and "To:" 154 | JPanel ftPanel = new JPanel(); 155 | ftPanel.setLayout(new BoxLayout(ftPanel, BoxLayout.Y_AXIS)); 156 | ftPanel.add(new JLabel(Language.get("MainFrame.SupPanel.SourcePath")+" ")); 157 | ftPanel.add(new JLabel(Language.get("MainFrame.SupPanel.DestinationPath")+" ")); 158 | 159 | 160 | //Subpanel with "source path" and "destination file" 161 | JPanel sourceDestPanel = new JPanel(); 162 | sourceDestPanel.setLayout(new BoxLayout(sourceDestPanel, BoxLayout.Y_AXIS)); 163 | sourceDestPanel.add(this.currentFileSource); 164 | sourceDestPanel.add(this.currentFileDestination); 165 | 166 | stringPanel.add(ftPanel); 167 | stringPanel.add(sourceDestPanel); 168 | stringPanel.add(Box.createVerticalStrut(15)); 169 | this.add(stringPanel); 170 | } 171 | 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/minicopier/gui/TransfersPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | TransfersPanel.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.gui; 21 | 22 | import java.awt.BorderLayout; 23 | import java.awt.Component; 24 | import java.awt.Dimension; 25 | 26 | import javax.swing.*; 27 | import javax.swing.table.*; 28 | 29 | import minicopier.i18n.Language; 30 | 31 | //Panel with transfer list 32 | public class TransfersPanel extends JPanel { 33 | 34 | private MainFrame mainFrame; 35 | 36 | protected QueueJButton putFirst; 37 | 38 | protected QueueJButton putUp; 39 | 40 | protected QueueJButton putDown; 41 | 42 | protected QueueJButton putLast; 43 | 44 | protected QueueJButton delete; 45 | 46 | protected DefaultTableModel transferModel; 47 | 48 | protected JTable transferList; 49 | 50 | public TransfersPanel(MainFrame f){ 51 | super(); 52 | 53 | this.mainFrame = f; 54 | 55 | this.putFirst = new QueueJButton("img/first.gif"); 56 | this.putFirst.setToolTipText(Language.get("Tooltip.Transfers.First")); 57 | 58 | this.putUp = new QueueJButton("img/up.gif"); 59 | this.putUp.setToolTipText(Language.get("Tooltip.Transfers.Up")); 60 | this.putDown = new QueueJButton("img/down.gif"); 61 | this.putDown.setToolTipText(Language.get("Tooltip.Transfers.Down")); 62 | this.putLast = new QueueJButton("img/last.gif"); 63 | this.putLast.setToolTipText(Language.get("Tooltip.Transfers.Last")); 64 | this.delete = new QueueJButton("img/delete.gif"); 65 | this.delete.setToolTipText(Language.get("Tooltip.Transfers.Cancel")); 66 | 67 | transferModel = mainFrame.copier.mainQueue.getTableModel(); 68 | transferList = new JTable(transferModel); 69 | //transferList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 70 | transferList.getColumnModel().getColumn(1).setCellRenderer(new RightTableCellRenderer()); 71 | transferList.getColumnModel().getColumn(1).setMaxWidth(80); 72 | transferList.getColumnModel().getColumn(1).setMinWidth(80); 73 | 74 | 75 | 76 | this.setLayout(new BorderLayout()); 77 | 78 | 79 | JScrollPane jspTransfer = new JScrollPane(transferList); 80 | jspTransfer.setViewportView(transferList); 81 | jspTransfer.setPreferredSize(new Dimension(40,40)); 82 | //transferList.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); 83 | //jspTransfer.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 84 | 85 | 86 | //Subpanel (west) with queue management buttons 87 | JPanel queueButtonsPanel = new JPanel(); 88 | queueButtonsPanel.setLayout(new BoxLayout(queueButtonsPanel, BoxLayout.Y_AXIS)); 89 | queueButtonsPanel.setAlignmentX(Component.CENTER_ALIGNMENT); 90 | queueButtonsPanel.add(this.putFirst,Component.CENTER_ALIGNMENT); 91 | queueButtonsPanel.add(this.putUp); 92 | queueButtonsPanel.add(this.putDown); 93 | queueButtonsPanel.add(this.putLast); 94 | queueButtonsPanel.add(this.delete); 95 | 96 | 97 | this.add(queueButtonsPanel,BorderLayout.WEST); 98 | this.add(jspTransfer,BorderLayout.CENTER); 99 | 100 | 101 | } 102 | 103 | public class RightTableCellRenderer extends DefaultTableCellRenderer { 104 | public RightTableCellRenderer() { 105 | setHorizontalAlignment(RIGHT); 106 | setVerticalAlignment(CENTER); 107 | } 108 | } 109 | 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/minicopier/i18n/Language.java: -------------------------------------------------------------------------------- 1 | /* 2 | Language.java / MiniCopier 3 | Copyright (C) 2007-2009 Adrian Courrèges 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License as 7 | published by the Free Software Foundation; either version 2 of 8 | the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | package minicopier.i18n; 21 | 22 | import java.util.*; 23 | 24 | public class Language { 25 | 26 | static ResourceBundle messages; 27 | 28 | /** If argument is "SystemLocale", we will use the system default locale. 29 | * Otherwise, we can force a language with : "fr", "en" ... 30 | * @param languageLocale "SystemLocale", "fr", "en" 31 | * */ 32 | public static void init(String languageLocale) { 33 | 34 | Locale locale; 35 | 36 | if (languageLocale.equals("SystemLocale")) { 37 | locale = Locale.getDefault(); 38 | } else { 39 | locale = new Locale(languageLocale); 40 | } 41 | 42 | Language.messages = ResourceBundle.getBundle("minicopier.i18n.minicopier",locale); 43 | 44 | 45 | } 46 | 47 | public static String get(String m) { 48 | return messages.getString(m); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/minicopier/i18n/minicopier.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/minicopier/i18n/minicopier.properties -------------------------------------------------------------------------------- /src/minicopier/i18n/minicopier_en.properties: -------------------------------------------------------------------------------- 1 | ## See minicopier.properties 2 | -------------------------------------------------------------------------------- /src/minicopier/i18n/minicopier_fr.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acourreges/minicopier/91cff5a1522d8f79080e1f32fb25b4468cb5b1fd/src/minicopier/i18n/minicopier_fr.properties --------------------------------------------------------------------------------